So, I've gotten some way since last. Now I have lightning and shadows, yay! But I have a few questions regarding my shaders for this.
I've got three textures I'm sampling from. Diffuse, Normal Map and a "Shadow map" that I've drawn to earlier.
String VERTEX = "#version 330 core" + "\n"
+ "uniform vec2 screen;" + "\n"
+ "layout(location = 0) in vec2 position;" + "\n"
+ "layout(location = 1) in vec2 texCoo;" + "\n"
+ "layout(location = 2) in float opacity;" + "\n"
+ "const vec2 trans = vec2(-1.0,1.0);" + "\n"
+ "out vec2 vTexCoo;" + "\n"
+ "out float vOpacity;" + "\n"
+ "out vec2 vShadowCoo;" + "\n"
+ "void main(){" + "\n"
+ "vTexCoo = texCoo;" + "\n"
+ "vOpacity = opacity;" + "\n"
+ "vShadowCoo = position*screen*0.5;" + "\n" // this texture has the same dimensions as the screen.
+ "gl_Position = vec4((position * screen)+trans, 0.0, 1.0);" + "\n"
+ "}";
1. My question regarding the vertex shader: As I've stated before, I'm using a truly dynamic VBO. As of now, I use a byte-buffer to add floats for all vertex information (I've noticed that byte-buffers are faster than float-buffers). Do you think it's better to send all vertex information as shorts? Thus saving 2x buffer space? I'm thinking about this, but it would require I modify a lot in my engine-code and I'm wondering if it's worth it.
String FRAGMENT = "#version 330 core" + "\n"
+ "in vec2 vTexCoo;" + "\n"
+ "in float vOpacity;" + "\n"
+ "in vec2 vShadowCoo;" + "\n"
+ "uniform sampler2D tex1;" + "\n"
+ "uniform sampler2D tex2;" + "\n"
+ "uniform sampler2D texShadow;" + "\n"
+ "uniform vec3 ambientDir;" + "\n"
+ "uniform vec3 ambientColor;" + "\n"
+ "uniform vec3[] lightPoss;" + "\n"
+ "uniform vec3[] lightColor;" + "\n"
+ "uniform int lightCount = 0;" + "\n"
+ "out vec4 fragColor;" + "\n"
+ "vec4 texColor;" + "\n"
+ "vec3 normal;" + "\n"
+ "vec4 shadowColor;" + "\n"
+ "vec3 tempColor;" + "\n"
+ "vec3 finalColor = vec3(0.0,0.0,0.0);" + "\n"
+ "vec3 lightDirection;" + "\n"
+ "float lightDistance;" + "\n"
+ "float dottis;" + "\n"
+ "void calcLight(vec3 lightP, vec3 lightC){" + "\n"
+ "lightDirection = vec3(lightP.xy - gl_FragCoord.xy, lightP.z);" + "\n"
+ "lightDistance = length(lightDirection);" + "\n"
+ "dottis = dot(normal.xyz, normalize(lightDirection));" + "\n"
+ "if (dottis > 0) {" + "\n"
+ "tempColor = lightC.xyz*dottis;" + "\n"
+ "tempColor.xyz /= pow(lightDistance, 3)*0.00012;" + "\n"
+ "if (shadowColor.x > 0.0)" + "\n"
+ "tempColor-= tempColor*shadowColor.x;" + "\n"
+ "finalColor += texColor.xyz * tempColor.xyz;" + "\n"
+ "}" + "\n"
+ "}" + "\n"
+ "void main(){" + "\n"
+ "texColor = texture2D(tex1, vTexCoo);" + "\n"
+ "if (texColor.w == 0){fragColor = vec4(0.0,0.0,0.0,0.0); return;}" + "\n"
+ "normal = normalize(texture2D(tex2, vTexCoo)*2.0 -1).xyz;" + "\n"
+ "shadowColor = texture2D(texShadow, vShadowCoo);" + "\n"
+ "tempColor;" + "\n"
+ "finalColor = vec3(0.0,0.0,0.0);" + "\n"
//Ambient
+ "dottis = dot(normal.xyz, ambientDir);" + "\n"
+ "if (dottis > 0)" + "\n"
+ "finalColor += texColor.xyz * ambientColor*dottis;" + "\n"
//lights
+ "if (lightCount > 0){" + "\n"
+ "calcLight(lightPoss[0], lightColor[0]);" + "\n"
+ "if (lightCount > 1){" + "\n"
+ "calcLight(lightPoss[1], lightColor[1]);" + "\n"
+ "if (lightCount > 2){" + "\n"
+ "calcLight(lightPoss[2], lightColor[2]);" + "\n"
+ "if (lightCount > 3){" + "\n"
+ "calcLight(lightPoss[3], lightColor[3]);" + "\n"
+ "if (lightCount > 4){" + "\n"
+ "calcLight(lightPoss[4], lightColor[4]);" + "\n"
+ "if (lightCount > 5){" + "\n"
+ "calcLight(lightPoss[5], lightColor[5]);" + "\n"
+ "if (lightCount > 6){" + "\n"
+ "calcLight(lightPoss[6], lightColor[6]);" + "\n"
+ "if (lightCount > 7){" + "\n"
+ "calcLight(lightPoss[7], lightColor[7]);" + "\n"
+ "if (lightCount > 8){" + "\n"
+ "calcLight(lightPoss[8], lightColor[8]);" + "\n"
+ "if (lightCount > 9){" + "\n"
+ "calcLight(lightPoss[9], lightColor[9]);" + "\n"
+ "if (lightCount > 10){" + "\n"
+ "calcLight(lightPoss[10], lightColor[10]);" + "\n"
+ "if (lightCount > 11){" + "\n"
+ "calcLight(lightPoss[11], lightColor[11]);" + "\n"
+ "if (lightCount > 12){" + "\n"
+ "calcLight(lightPoss[12], lightColor[12]);" + "\n"
+ "if (lightCount > 13){" + "\n"
+ "calcLight(lightPoss[13], lightColor[13]);" + "\n"
+ "if (lightCount > 14){" + "\n"
+ "calcLight(lightPoss[14], lightColor[14]);" + "\n"
+ "if (lightCount > 15){" + "\n"
+ "calcLight(lightPoss[15], lightColor[15]);" + "\n"
+ "if (lightCount > 16){" + "\n"
+ "calcLight(lightPoss[16], lightColor[16]);" + "\n"
+ "if (lightCount > 17){" + "\n"
+ "calcLight(lightPoss[17], lightColor[17]);" + "\n"
+ "if (lightCount > 18){" + "\n"
+ "calcLight(lightPoss[18], lightColor[18]);" + "\n"
+ "if (lightCount > 19){" + "\n"
+ "calcLight(lightPoss[19], lightColor[19]);" + "\n"
+ "}}}}}}}}}}}}}}}}}}}}" + "\n"
+ "fragColor = vec4(finalColor, texColor.w*vOpacity);" + "\n"
+ "}" + "\n";
2. first of all. Do I need this:
"if (texColor.w == 0){fragColor = vec4(0.0,0.0,0.0,0.0); return;}" + "\n"
Or do you think the compiler is smart enough to manage without this?
3. What about the calculation of light distance. Now, I'm doing this in the fragment shader. I could do this in the vertex shader, but I'm thinking that the vetex would basically do the same number of operations when it interpolates, so now sure there'd be a gain.
4. My biggest concern is whether the pipeline is smart enough not to process vertices and fragments that are obscured by others. Like if I draw one background picture first, then another that covers the first completely, then swap buffers. Will the GPU process the obscured one, then the overlaying one? I'm not using the depth buffer.