Default vertex shader

BlitzMax Forums/MiniB3D Module/Default vertex shader

BlitzSupport(Posted 2016) [#1]
Hi all,

Does anyone know how to locate (or define the equivalent of) the default vertex shader, ie. what openb3d uses if you call LoadShader "", "", "my_fragshader.glsl"? (Note "" for vertex shader filename, the second parameter.)

I'm just playing about with very simple pixel/fragment shading and want a baseline vertex shader (in .glsl form) to go with my fragment shader, just so I have an idea what I'm working with, can potentially learn to tweak, etc. I tried copying shaders/default.vert.glsl but that results in black output no matter what, whereas if I leave the vertex shader as "" it works.

I tried going through the sources, but can't see it defined anywhere; I can see material.cpp -> Shader::AddShader, but that doesn't seem to have a path for when no filename is supplied -- so does GLSL use a default vertex shader if none is supplied, or am I just failing to find it?

I just want the equivalent .glsl to match the default vertex shader, to sit alongside my fragment shader .glsl file for reference. (Would prefer to know it's giving me exactly the same environment, rather than just one that works.)

For what it's worth, this is my simple pixel shader -- simply renders yellow into a texture that's been applied to a sprite:

// basic.frag.glsl:

uniform sampler2D texture0;

void main()
{
    vec4 pixel = texture2D(texture0, gl_FragCoord.xy);
	
	pixel.r = 1.0;
	pixel.g = 1.0;
	pixel.b = 0.0;
	
	pixel.a = 1.0;
	
	gl_FragColor = pixel;
}


... and test code:



Thanks for any pointers!


RustyKristi(Posted 2016) [#2]
Yes, with OpenB3D it is weird but it works and you don't have to put one unless you will need it in your fragment shader part. ie depth or light position that sort of thing.


BlitzSupport(Posted 2016) [#3]
OK, this seems to be what I needed:

// basic.vert.glsl:

void main()
{
	gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
}


... which is loaded via this minor tweak to the above test code:

Local shader:TShader	= LoadShader ("", "basic.vert.glsl", "basic.frag.glsl")


At least gives the same visual result so far!


angros47(Posted 2016) [#4]
I remind you that gl_ModelViewProjectionMatrix will be deprecated in the later versions of OpenGL


BlitzSupport(Posted 2016) [#5]
Hmm, any idea how I would do this without gl_ModelViewProjectionMatrix?


angros47(Posted 2016) [#6]
There is the command UseMatrix, in OpenB3D


col(Posted 2016) [#7]
@BlitzSupport

I'm not so good with OpenGL specifics as I'm more into DirectX and Vulkan, but I believe it would be a uniform parameter in Max and shader code.

In your Max code you have your matrices: a world matrix for the geometry, a view matrix for the 'camera' and a projection matrix for the 'camera'.
In true programming style there are many ways to achieve the same result and it depends on what you actually want and how you want to achieve it. Ultimately you need to calculate that MVP matrix yourself. You can either do it in your Max code on a 'per frame' basis, or give the matrices to the shader ( via the uniforms I believe ) and calculate the final MVP matrix in the shader itself on a 'per vertex' basis.

It really depends on what the shader does, bearing in mind that if you have the shader calculate the MVP then it will do that calculation for every single vertex. If you calculate the MVP in the BMax code then the shader doesn't need to do it, giving you an optimisation.

I generally use 2 matrices, the model/world matrix( which changes for each model that you want to draw, many models per frame ) and a 'per frame' ViewProjection matrix ( as the 'camera' position/rotation and projection doesn't change between frames ) in my shaders. Again it just depends on what the shader itself requires, which again depends on what the shader is actually doing as to what components it needs.

So in my shaders I have, the equivalent of 2 matrix uniforms, 1 model matrix and 1 viewprojection matrix. I multiply the vertex by the model matrix then multiply that result by the viewprojection matrix.

Sorry I don't know the specifics for setting up the uniforms, assuming that my GL terminology is correct? :p


BlitzSupport(Posted 2016) [#8]
Thanks, guys... just been trying to make this work, but I'm still stuck!

I've amended to:


SuperStrict

Import Openb3d.B3dglgraphics

Graphics3D 1024, 768, 0, 2

Local cam:TCamera		= CreateCamera ()

Local light:TLight		= CreateLight (1)

Local sprite:TSprite	= CreateSprite ()

Local tex:TTexture		= CreateTexture (512, 512, 1 | 256)

Local shader:TShader	= LoadShader ("", "basic.vert.glsl", "basic.frag.glsl")

MoveEntity cam,		0.0,	0.0,	-5.0
MoveEntity light,	-5.0,	5.0,	-2.0
PointEntity light,	sprite

EntityTexture sprite, tex

If shader
	ShaderTexture	shader, tex, "texture0"
	ShadeEntity		sprite, shader
Else
	RuntimeError "Failed to load shader"
EndIf

Repeat

	UseMatrix shader, "gl_mvp_matrix", 0

	Cls
	
	RenderWorld
	
	Flip
	
Until KeyHit (KEY_ESCAPE)

End


... with vertex shader defined as:

uniform mat4 gl_mvp_matrix;

void main()
{
	gl_Position = gl_mvp_matrix * gl_Vertex;
}


... and fragment shader as before, but now I just get a black screen. (Not sure if I need to call UseMatrix per-frame?)

I've tried to base this off sl_usematrix.bmx and usematrix.vert.glsl, but in that shader, it doesn't look like it's even using the resulting position_in_world_space vec4, which is calculated from the mat4 passed via UseShader:

// en.wikibooks.org/wiki/GLSL_Programming/Unity/Shading_in_World_Space

uniform mat4 _Object2World; // definition of a matrix uniform variable 

varying vec4 position_in_world_space;

void main()
{
	position_in_world_space = _Object2World * gl_Vertex;
	// transformation of gl_Vertex from object coordinates to world coordinates;

	gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
}


(position_in_world_space is calculated, but gl_ModelViewProjectionMatrix is used after that anyway.)

I'm also not sure what I should be passing in the mode parameter of UseShader -- I can't find a list of mode definitions anywhere in the source/docs, just the comment given in the sl_usershader.bmx example, "0=model matrix".

Not even sure what mode I should be passing here -- is it model, view, projection? I really just need enough to operate on a single quad/texture, really, which would be stretched to fill the display.


col(Posted 2016) [#9]
James,

I hope I don't confuse the issue any more as I'm not sure how OpenB3D is setup, but if all you really do want is a full screen quad, then you don't need any matrices at all. The gpu works in what are called 'normalized device coordinates' which means that the screen coordinates will range from -1 to +1 in all 3 dimensions ( although the z ranges from 0 to 1 in DirectX - go figure ). The matrices are purely for projection and world scaling so that we move our 3d objects within say 1000 x 1000 x 1000 instead of -1 to +1 range, and the matrices scale everything back into the NDC while making objects that are further away converge to the centre of the screen ( or more accurately, the viewport )

What this means is that you can have 2 triangles, who vertices range from -1 to +1 in the x,y with z as 0. You don't even have to have UVs as you can calculate them too in the vertex shader from the incoming vertex position, but I suppose you could set UVs in your cpu side geometry.

You then use what is known as a 'pass through shader' for the vertex shader, which I guess would be something like 'gl_Position = gl_Vertex' and you will get a full screen quad.


RustyKristi(Posted 2016) [#10]
You should check the shader examples provided by munch. It's very simple to follow starting with the greyscale shader. Just copy the process on how it should be setup.

https://github.com/markcwm/openb3d.mod/blob/master/examples/extended/sl_greyscale.bmx

You can also do multiple passess using multiple camera textures with it's own flip technique.

https://github.com/markcwm/openb3d.mod/blob/master/examples/extended/sl_blur2pass.bmx


BlitzSupport(Posted 2016) [#11]
Thanks for all the help, guys, think I have it now -- simple 'screen-space' yellow sprite shader:

example.bmx:


SuperStrict

Import Openb3d.B3dglgraphics

Graphics3D 1024, 768, 0, 2

Local cam:TCamera		= CreateCamera ()

Local light:TLight		= CreateLight (1)

Local sprite:TSprite	= CreateSprite ()

Local tex:TTexture		= CreateTexture (256, 256, 1 | 256)

Local shader:TShader	= LoadShader ("", "basic.vert.glsl", "basic.frag.glsl")

MoveEntity cam,		0.0,	0.0,	-5.0
MoveEntity light,	-5.0,	5.0,	-2.0
PointEntity light,	sprite

EntityTexture sprite, tex

Rem

	UseMatrix modes, from Shader::UseMatrix () in
	openb3d.mod\openb3dlib.mod\openb3d\src\material.cpp:

	0 = model matrix
	1 = view matrix
	2 = projection matrix
	3 = modelview matrix

EndRem

UseMatrix shader, "matrix_projection", 2
UseMatrix shader, "matrix_modelview", 3

If shader
	ShaderTexture	shader, tex, "texture0"
	ShadeEntity		sprite, shader
Else
	RuntimeError "Failed to load shader"
EndIf

Repeat

	Cls
	
	RenderWorld
	
	Flip
	
Until KeyHit (KEY_ESCAPE)

End



basic.vert.glsl:


uniform mat4 matrix_projection;
uniform mat4 matrix_modelview;

void main()
{
	gl_Position = matrix_projection * matrix_modelview * gl_Vertex;
}



basic.frag.glsl:


void main()
{
	gl_FragColor = vec4(1.0, 1.0, 0.0, 1.0);
}



(Anyone see any problems with this?)


BlitzSupport(Posted 2016) [#12]
Meant to say, that passthrough shader seems to work, col! Handy to have...