How to create a custom 3d Material shader?


#1

I create a simple cube like this:

function getCube(s3d, color:Int) {
  var mat = Material.create();
  mat.color.setColor(color);

  var cube = new Cube(1, 1, 1);
  cube.translate(0.5, 0.5, 0.5);

  cube.unindex();
  cube.addNormals();

  var obj = new Mesh(cube, mat, s3d);
  obj.material.mainPass.enableLights = true;
  return obj;
}

Then I use it like this:

var box = getCube(s3d, 0x75a85b);

image

I have this shader (it does nothing):

class WallShader extends hxsl.shader.BaseMesh {
	static var SRC = {

	};
}

I enable the shader like this:

var box = getCube(s3d, 0x75a85b);

var shader:WallShader = new WallShader();
shader.id = Math.random();
box.material.mainPass.addShader(shader);

But then my cube looks like this:
image

Question: Why is that?


I suspect that extends BaseMesh is cause of issue, but this contains lot of useful variables which I want to use (like input.position and output.color etc). What am I missing?


#2
  1. Just declare input with position in it, iirc, Heaps should bind those correctly automatically.
  2. You can also use @:import h3d.shader.BaseMesh (or something like that) inside SRC
  3. You shouldn’t assign output.position directly (or any BaseShader output variables), use the ones provided by BaseShader, by declaring them in your shader (or if you use @:import - most of them are declared automatically). In your case instead of output.color you should use pixelColor.
  4. Same goes for input - most of them are assigned a variable. Those variables can be edited, and utilized by several shaders in a pass consequently.
// If you need input data, you can just declare it:
@input var input : { var position:Vec3; }
// If you want to import declaractions from other shader, use @:import
// I don't remember what is and isn't imported.
// Also potentially can lead to name conflicts.
@:import h3d.shader.BaseShader
// Inputs/outputs have variables assigned to them,
// so it's better to use them, because they can be modified
// by other shaders before and after this shader code.
var relativePosition : Vec3;
var pixelColor : Vec4;
// In vertex: instead of input.position
relativePosition += vec3(0,0,10);
// In fragment: Instead of output.color
pixelColor = grayscale(pixelColor);

When you’ll use those variables they’ll contain values that were assigned to them in __init__ method of BaseShader (and other shaders that have __init__ and use that variable in it)

As to answer your question “Why extending BaseMesh does that”: Well… You replaced BaseMesh with an empty shader, what else did you expect? : D Actually, strike that. Most likely it’s just conflict of shaders, as you add it twice.