tl;dr:
What is the best method for accessing data from each individual vertex whilst in the fragment shader?
e.g.
The triangle in this fragment is made up from vertices v0,v1 and v2 and I want to give each vertex a specific integer which I can use to pick a texture and then fade between the 3 in the fragment shader; I don't want these ids to be interpolated and it is important that I can access each vertex's id.
Current Situation:
I am currently writing a shader for rendering terrain; I have a function in my fragment shader which will return the appropriate texture colour from uvs for a given ID (By means of a texture atlas). I can then fade between the 3 textures to give the give smoothly textured terrain
Current Code
Vertex Shader:
#version 330 core
layout(location = 0) in vec3 in_position;
layout(location = 1) in vec2 in_uv_coords;
layout(location = 2) in vec3 in_normal;
layout(location = 3) in float in_texture_id;
uniform mat4 view_matrix;
uniform mat4 projection_matrix;
out vec2 pass_uv_coords;
out vec3 pass_normal;
out vec3 texture_ratio;
out float pass_fake_brightness;
out float pass_id0;
out float pass_id1;
out float pass_id2;
void CalculateFakeLighting()
{
const vec3 light_direction = normalize(vec3(1,-1,1));
vec3 unit_normal = normalize(in_normal);
float normal_dot_light = dot(unit_normal, -light_direction);
pass_fake_brightness = max(0.2, normal_dot_light);
}
void main()
{
pass_uv_coords = in_uv_coords;
pass_normal = in_normal;
gl_Position = projection_matrix * view_matrix * vec4(in_position, 1.0);
int tile_track = int(mod(gl_VertexID, 3));
switch(tile_track)
{
case 0:
texture_ratio = vec3(1,0,0);
pass_id0 = in_texture_id;
break;
case 1:
texture_ratio = vec3(0,1,0);
pass_id1 = in_texture_id;
break;
case 2:
texture_ratio = vec3(0,0,1);
pass_id0 = in_texture_id;
break;
};
CalculateFakeLighting();
}
Fragment Shader:
#version 330 core
in vec2 pass_uv_coords;
in vec3 pass_normal;
in vec3 texture_ratio;
in float pass_fake_brightness;
in float pass_id0;
in float pass_id1;
in float pass_id2;
const int HORIZONTAL_IDS = 8;
const int VERTICAL_IDS = 8;
uniform sampler2D texture0_sampler;
out vec4 colour;
void UseFakeLighting()
{
colour *= pass_fake_brightness;
}
vec2 CorrectUVs(vec2 uvs)
{
vec2 corrected_uvs = uvs;
const float cushion = 0.001;
//Correct UV scale
while(corrected_uvs.x >= 1)
corrected_uvs.x--;
while(corrected_uvs.y >= 1)
corrected_uvs.y--;
if(corrected_uvs.x < cushion)
corrected_uvs.x = cushion;
if(corrected_uvs.x > 1 - cushion)
corrected_uvs.x = 1 - cushion;
if(corrected_uvs.y < cushion)
corrected_uvs.y = cushion;
if(corrected_uvs.y > 1 - cushion)
corrected_uvs.y = 1 - cushion;
return corrected_uvs;
}
vec4 GetTexture(float id, vec2 uv_coords)
{
vec2 step = vec2(
1.0/HORIZONTAL_IDS,
1.0/VERTICAL_IDS
);
uv_coords.x/=HORIZONTAL_IDS;
uv_coords.y/=VERTICAL_IDS;
uv_coords.x += step.x * mod(id, HORIZONTAL_IDS);
uv_coords.y += step.y * floor(id/VERTICAL_IDS);
//Texture is upsidedown
uv_coords.y = 1.0 - uv_coords.y;
return texture(texture0_sampler, uv_coords);
}
void main()
{
vec2 corrected_uvs = CorrectUVs(pass_uv_coords);
vec3 correct_ratio = normalize(texture_ratio);
colour = GetTexture(pass_id0, corrected_uvs) * correct_ratio.x +
GetTexture(pass_id1, corrected_uvs) * correct_ratio.y +
GetTexture(pass_id2, corrected_uvs) * correct_ratio.z;
if(colour.a == 0)
discard;
UseFakeLighting();
}
By default the output variables from the vertex shader to the fragment shader use perspective-correct interpolation. If you want no interpolation done then qualify your variables with flat:
flat out vec3 pass_id0;
For more info see GLSL Type Qualifiers. Also see this question “flat” qualifier in glsl?
As recommended by #aslg and #AndonM.Coleman, geometry is a good solution to this issue. A flat vec3 is passed out of the geometry stage, which stores the id of each vertex which is then accessible in the fragment shader.
The key lines are in the geometry shader; one part of the output is
flat vec3 texture_ids;
Which is then set as such:
vertex_out.texture_ids.x = vertex_in[0].texture_id;
vertex_out.texture_ids.y = vertex_in[1].texture_id;
vertex_out.texture_ids.z = vertex_in[2].texture_id;
Full Shader Sources:
Vertex
#version 330 core
layout(location = 0) in vec3 in_position;
layout(location = 1) in vec2 in_uv_coords;
layout(location = 2) in vec3 in_normal;
layout(location = 3) in float in_texture_id;
out VertexData
{
vec2 uv_coord;
vec3 normal;
uint texture_id;
} vertex_out;
void main()
{
vertex_out.uv_coord = in_uv_coords;
vertex_out.normal = in_normal;
vertex_out.texture_id = uint(round(in_texture_id));
gl_Position = vec4(in_position, 1.0);
}
Geometry
#version 330 core
layout (triangles) in;
layout (triangle_strip, max_vertices = 3) out;
uniform mat4 view_matrix;
uniform mat4 projection_matrix;
mat4 vp_matrix = projection_matrix * view_matrix;
in VertexData
{
vec2 uv_coord;
vec3 normal;
uint texture_id;
} vertex_in[];
out VertexDataPass
{
vec2 uv_coord;
vec3 normal;
vec3 texture_ratio;
float brightness;
flat vec3 texture_ids;
} vertex_out;
void CalculateFakeBrightness(int index)
{
const vec3 light_direction = normalize(vec3(1,-1,1));
vec3 unit_normal = normalize(vertex_in[index].normal);
float normal_dot_light = dot(unit_normal, -light_direction);
vertex_out.brightness = max(0.2, normal_dot_light);
}
void main()
{
for(int i = 0; i < gl_in.length(); i++)
{
gl_Position = vp_matrix * gl_in[i].gl_Position;
vertex_out.uv_coord = vertex_in[i].uv_coord;
vertex_out.normal = vertex_in[i].normal;
vertex_out.texture_ids.x = vertex_in[0].texture_id;
vertex_out.texture_ids.y = vertex_in[1].texture_id;
vertex_out.texture_ids.z = vertex_in[2].texture_id;
CalculateFakeBrightness(i);
switch(int(mod(i,3)))
{
case 0:
vertex_out.texture_ratio = vec3(1,0,0);
break;
case 1:
vertex_out.texture_ratio = vec3(0,1,0);
break;
case 2:
vertex_out.texture_ratio = vec3(0,0,1);
break;
};
EmitVertex();
}
EndPrimitive();
}
Fragment
#version 330 core
in VertexDataPass
{
vec2 uv_coord;
vec3 normal;
vec3 texture_ratio;
float brightness;
flat vec3 texture_ids;
} vertex_data;
const int HORIZONTAL_IDS = 8;
const int VERTICAL_IDS = 8;
uniform sampler2D texture0_sampler;
out vec4 colour;
vec2 CorrectUVs(vec2 uvs)
{
vec2 corrected_uvs = uvs;
const float cushion = 0.001;
//Correct UV scale
while(corrected_uvs.x >= 1)
corrected_uvs.x--;
while(corrected_uvs.y >= 1)
corrected_uvs.y--;
if(corrected_uvs.x < cushion)
corrected_uvs.x = cushion;
if(corrected_uvs.x > 1 - cushion)
corrected_uvs.x = 1 - cushion;
if(corrected_uvs.y < cushion)
corrected_uvs.y = cushion;
if(corrected_uvs.y > 1 - cushion)
corrected_uvs.y = 1 - cushion;
return corrected_uvs;
}
vec4 GetTexture(uint id, vec2 uv_coords)
{
vec2 step = vec2(
1.0/HORIZONTAL_IDS,
1.0/VERTICAL_IDS
);
uv_coords.x/=HORIZONTAL_IDS;
uv_coords.y/=VERTICAL_IDS;
uv_coords.x += step.x * mod(id, HORIZONTAL_IDS);
uv_coords.y += step.y * floor(float(id)/VERTICAL_IDS);
//Texture is upsidedown
uv_coords.y = 1.0 - uv_coords.y;
return texture(texture0_sampler, uv_coords);
}
void main()
{
vec2 uvs = CorrectUVs(vertex_data.uv_coord);
colour =
GetTexture(uint(vertex_data.texture_ids.x), uvs) * vertex_data.texture_ratio.x +
GetTexture(uint(vertex_data.texture_ids.y), uvs) * vertex_data.texture_ratio.y +
GetTexture(uint(vertex_data.texture_ids.z), uvs) * vertex_data.texture_ratio.z;
if(colour.a == 0)
discard;
colour.xyz *= vertex_data.brightness;
}
Related
Does anyone know why I keep getting the error that says:
The ♦ shader uses varying _I;DATA;g_mapCoord, but previous shader does not write to it.
The ♦ shader uses varying _I;DATA;worldPosition, but previous shader does not write to it.
Take a look at my shaders here.
Vertex
#version 430
layout (location = 0) in vec2 position0;
out DATA {
vec2 v_mapCoord;
vec3 worldPosition;
} Out;
uniform vec3 u_cameraPosition;
uniform mat4 u_localMatrix;
uniform mat4 u_worldMatrix;
uniform float u_scaleY;
uniform int u_lod;
uniform vec2 u_index;
uniform float u_gap;
uniform vec2 u_location;
uniform sampler2D s_heightmap;
uniform int u_lodMorphArea[8];
float morphLatitude(vec2 position)
{
//not important code
return 0;
}
float morphLongitude(vec2 position)
{
//not important code
return 0;
}
vec2 morph(vec2 localPosition, int morph_area){
//not important code
return vec2(0);
}
void main()
{
vec2 localPosition = (u_localMatrix * vec4(position0.x,0,position0.y,1)).xz;
if (u_lod > 0) {
localPosition += morph(localPosition, u_lodMorphArea[u_lod-1]); // Translate position by morphing vector
}
float height = texture(s_heightmap, localPosition).r;
Out.v_mapCoord = localPosition;
vec4 _worldPosition = u_worldMatrix * vec4(localPosition.x, height, localPosition.y,1);
Out.worldPosition = _worldPosition.xyz;
gl_Position = u_worldMatrix * vec4(localPosition.x, height, localPosition.y,1);
}
Fragment
#version 430
layout (location = 0) out vec4 outputColor;
in DATA {
vec2 g_mapCoord;
vec3 worldPosition;
} In;
const vec3 lightDirection = vec3(-0.2, -1.0, -0.2);
const float intensity = 1.2;
uniform sampler2D s_textureNormal;
uniform sampler2D s_textureWater;
uniform sampler2D s_textureLand;
float diffuse(vec3 direction, vec3 normal, float intensity)
{
return max(0.01, dot(normal, -direction) * intensity);
}
void main()
{
vec3 normal = texture(s_textureNormal, In.g_mapCoord).rgb;
float diff = diffuse(lightDirection, normal, intensity);
outputColor = vec4(1,0,0,1);
}
Geom
#version 430
layout(triangles) in;
layout(triangle_strip, max_vertices = 3) out;
in vec2 te_mapCoord[];
out vec2 g_mapCoord;
uniform mat4 u_viewProjection;
void main() {
for (int i = 0; i < gl_in.length(); ++i)
{
vec4 position = gl_in[i].gl_Position;
gl_Position = u_viewProjection * position;
g_mapCoord = te_mapCoord[i];
EmitVertex();
}
EndPrimitive();
}
TCS
#version 430
layout(vertices = 16) out;
in DATA {
vec2 v_mapCoord;
vec3 worldPosition;
} In[];
out vec2 tc_mapCoord[];
const int AB = 2;
const int BC = 3;
const int CD = 0;
const int DA = 1;
uniform int u_tessellationFactor;
uniform float u_tessellationSlope;
uniform float u_tessellationShift;
uniform vec3 u_cameraPosition;
// Calculate tessellation levels
float lodFactor(float dist)
{
float tessellationLevel = max(0.0, u_tessellationFactor/pow(dist, u_tessellationSlope) + u_tessellationShift);
return tessellationLevel;
}
void main()
{
if (gl_InvocationID == 0){
// Calculate mid points of the edges of the quad
vec3 abMid = vec3(gl_in[0].gl_Position + gl_in[3].gl_Position)/2.0; //Bottom left, Bottom right
vec3 bcMid = vec3(gl_in[3].gl_Position + gl_in[15].gl_Position)/2.0; //Bottom right Top right
vec3 cdMid = vec3(gl_in[15].gl_Position + gl_in[12].gl_Position)/2.0; //Top right, Top left
vec3 daMid = vec3(gl_in[12].gl_Position + gl_in[0].gl_Position)/2.0; //Top left, Bottom left
// Calculate distance between camera and mid points of the edges of the quad
float distanceAB = distance(abMid, u_cameraPosition);
float distanceBC = distance(bcMid, u_cameraPosition);
float distanceCD = distance(cdMid, u_cameraPosition);
float distanceDA = distance(daMid, u_cameraPosition);
// Tesselation levels used by tessellation primitive generator (define how much tessellation to apply to the patch). Value between 1 and gl_MaxTessGenLevel, depending on lodFactor.
gl_TessLevelOuter[AB] = mix(1, gl_MaxTessGenLevel, lodFactor(distanceAB));
gl_TessLevelOuter[BC] = mix(1, gl_MaxTessGenLevel, lodFactor(distanceBC));
gl_TessLevelOuter[CD] = mix(1, gl_MaxTessGenLevel, lodFactor(distanceCD));
gl_TessLevelOuter[DA] = mix(1, gl_MaxTessGenLevel, lodFactor(distanceDA));
gl_TessLevelInner[0] = (gl_TessLevelOuter[BC] + gl_TessLevelOuter[DA])/4;
gl_TessLevelInner[1] = (gl_TessLevelOuter[AB] + gl_TessLevelOuter[CD])/4;
}
tc_mapCoord[gl_InvocationID] = In[gl_InvocationID].v_mapCoord; // Just pass to the next stage
gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;
}
TES
#version 430
layout(quads, fractional_odd_spacing, cw) in;
in vec2 tc_mapCoord[];
out vec2 te_mapCoord;
uniform sampler2D s_heightmap;
uniform float u_scaleY;
void main(){
float u = gl_TessCoord.x;
float v = gl_TessCoord.y;
// Compute new position for each tessellated vertex within the patch. gl_in with index 12, 0, 3, 15 are corners of the patch.
vec4 position = ((1 - u) * (1 - v) * gl_in[12].gl_Position + u * (1 - v) * gl_in[0].gl_Position + u * v * gl_in[3].gl_Position +(1 - u) * v * gl_in[15].gl_Position);
vec2 mapCoord = ((1 - u) * (1 - v) * tc_mapCoord[12] + u * (1 - v) * tc_mapCoord[0] + u * v * tc_mapCoord[3] +(1 - u) * v * tc_mapCoord[15]);
float height = texture(s_heightmap, mapCoord).r;
height *= u_scaleY;
position.y = height;
te_mapCoord = mapCoord;
gl_Position = position;
}
Can anyone help me find the error here which is why I'm getting that error message?
When you introduce a geometry shader you need to pass the varyings for the fragment shader from the geometry shader, not the vertex shader.
You can see how your geometry shader doing this:
out vec2 g_mapCoord;
is incompatible with your fragment shader expecting this:
in DATA {
vec2 g_mapCoord;
vec3 worldPosition;
} In;
Related question and subsequent answers here.
The problem is that artifacts appear in the shadows at a great distance. I want to try to make a logarithmic depth buffer, but I don’t understand where it should be done and how ... I use point light method for omnidirectional shadow maps
Vertex shader:
#version 460 core
layout (location = 0) in vec3 aPos;
uniform mat4 model;
uniform float zCoef;
//out vec4 pos;
void main() {
gl_Position = model * vec4(aPos, 1.0f);
// gl_Position.z = log2(max(1e-6, gl_Position.w + 1.0)) * zCoef - 1.0;
// gl_Position.z *= gl_Position.w;
}
Geometry shader:
#version 460 core
layout (triangles) in;
layout (triangle_strip, max_vertices = 18) out;
uniform mat4 shadowMatrices[6];
uniform float zCoef;
out vec4 FragPos; // FragPos from GS (output per emitvertex)
void main()
{
for(int face = 0; face < 6; ++face)
{
gl_Layer = face; // встроенная переменная, указывающая на то, какую грань мы рендерим
for(int i = 0; i < 3; ++i) // для каждой вершины треугольника
{
FragPos = gl_in[i].gl_Position;
gl_Position = shadowMatrices[face] * FragPos;
// gl_Position.z = log2(max(1e-6, gl_Position.w + 1.0)) * zCoef - 1.0;
// gl_Position.z *= gl_Position.w;
EmitVertex();
}
EndPrimitive();
}
}
Fragment shader:
#version 460 core
in vec4 FragPos;
uniform vec3 lightPos;
uniform float farPlane;
uniform float zCoef;
void main() {
float lightDistance = length(FragPos.xyz - lightPos);
lightDistance = lightDistance / farPlane;
gl_FragDepth = lightDistance;
}
Guys, pls help me,i tried to use the linearization depth, it didn't work too..
I'm trying to call glGetUniformLocation() on an array of struct. I read that I should use this name format: "uniformName[index].element", but the method always returns -1. I tried to delete the array and only use the structure and it worked so I guess that the problem might there. Here is the struct and the array in my fragment shader:
const int MAX_BLOCKS = 16;
struct sblock{
vec4 color;
float shineDamper;
float reflectivity;
};
uniform sblock blocks[MAX_BLOCKS];
And here is my call:
for(int i = 0; i < 16; i++) {
location_block_color[i] = super.getUniformLocation("blocks["+i+"].color");
location_block_reflectivity[i] = super.getUniformLocation("blocks["+i+"].reflectivity");
location_block_shineDamper[i] = super.getUniformLocation("blocks["+i+"].shineDamper");
System.out.println(location_block_color[i] + " " + location_block_reflectivity[i] + " " + location_block_shineDamper[i]); // prints -1 -1 -1 ...
}
getUniformLocation method:
protected int getUniformLocation(String uniformName) {
return GL20.glGetUniformLocation(programID, uniformName);
}
and this how I create programID (before anything else):
vertexShaderID = loadShader(vertexFile, GL20.GL_VERTEX_SHADER);
fragmentShaderID = loadShader(fragmentFile, GL20.GL_FRAGMENT_SHADER);
programID = GL20.glCreateProgram();
My question is what is happening here and what am I doing wrong?
Thanks for your help.
EDIT 1:
Here is my full fragment shader:
#version 400 core
const int MAX_LIGHTS = 16;
const int MAX_BLOCKS = 16;
struct sblock{
vec4 color;
float shineDamper;
float reflectivity;
};
uniform sblock blocks[MAX_BLOCKS];
in int block_id_out;
in vec3 unitNormal;
in vec3 lightVector[MAX_LIGHTS];
in vec3 directionalLightFinalColour;
in vec3 directionalLightReflected;
in vec3 toCameraVector;
in float visibility;
out vec4 outColor;
uniform float ambientLight;
uniform vec3 skyColor;
uniform vec3 lightColour[MAX_LIGHTS];
uniform vec3 attenuation[MAX_LIGHTS];
uniform int lightCount;
uniform vec3 directionalLightColour;
uniform vec3 directionalLightDirection;
vec3 calculateDiffuse(vec3 unitNormal, vec3 unitLightVector, vec3 lightColour, float attFactor){
float nDotl = dot(unitNormal,unitLightVector);
float brightness = max(nDotl,0);
return (brightness * lightColour) / attFactor;
}
vec3 calculateSpecular(vec3 unitNormal, vec3 unitLightVector, vec3 unitToCameraVector, float shineDamper, float reflectivity, vec3 lightColour, float attFactor){
vec3 reflectedLightDirection = reflect(-unitLightVector,unitNormal);
float specularFactor = max(dot(reflectedLightDirection, unitToCameraVector),0.0);
float dampedFactor = pow(specularFactor,shineDamper);
return (dampedFactor * reflectivity * lightColour) / attFactor;
}
void main(void){
vec3 totalDiffuse = vec3(0.0);
vec3 totalSpecular = vec3(0.0);
vec3 unitToCameraVector = normalize(toCameraVector);
for(int i = 0; i < lightCount;i++){
vec3 unitLightVector = normalize(lightVector[i]);
float lightDistance = length(lightVector[i]);
float attFactor = attenuation[i].x + attenuation[i].y*lightDistance + attenuation[i].z*lightDistance*lightDistance;
totalSpecular += calculateSpecular(unitNormal, unitLightVector, unitToCameraVector, blocks[block_id_out].shineDamper, blocks[block_id_out].reflectivity, lightColour[i], attFactor);
totalDiffuse += calculateDiffuse(unitNormal, unitLightVector, lightColour[i], attFactor);
}
totalDiffuse += directionalLightFinalColour;
totalSpecular += pow(max(dot(directionalLightReflected,unitToCameraVector),0.0),blocks[block_id_out].shineDamper)*blocks[block_id_out].reflectivity*directionalLightColour;
totalDiffuse = max(totalDiffuse,ambientLight);
outColor = vec4(totalDiffuse,1.0) * blocks[block_id_out].color + vec4(totalSpecular,1.0);
outColor = mix(vec4(skyColor,1.0),outColor,visibility);
}
EDIT 2:
Here is my VertexShader:
#version 400 core
const vec4 normals[] = vec4[6](vec4(1,0,0,0),vec4(0,1,0,0),vec4(0,0,1,0),vec4(-1,0,0,0),vec4(0,-1,0,0),vec4(0,0,-1,0));
const int MAX_LIGHTS = 16;
in vec3 position;
in int block_id;
in int normal;
out int block_id_out;
out vec3 unitNormal;
out vec3 lightVector[MAX_LIGHTS];
out vec3 directionalLightFinalColour;
out vec3 directionalLightReflected;
out vec3 toCameraVector;
out float visibility;
uniform mat4 transformationMatrix;
uniform mat4 projectionMatrix;
uniform mat4 viewMatrix;
uniform vec3 lightPosition[MAX_LIGHTS];
uniform vec3 directionalLight;
uniform vec3 directionalLightColor;
uniform int lightCount;
uniform float fogDensity;
uniform float fogGradient;
void main(void){
vec4 worldPosition = transformationMatrix * vec4(position,1.0);
vec4 positionRelativeToCam = viewMatrix * worldPosition;
gl_Position = projectionMatrix * positionRelativeToCam;
block_id_out = block_id;
unitNormal = normalize((transformationMatrix * normals[normal]).xyz);
for(int i = 0; i < lightCount;i++){
lightVector[i] = lightPosition[i] - worldPosition.xyz;
}
directionalLightFinalColour = max(dot(unitNormal, directionalLight),0)*directionalLightColor;
directionalLightReflected = reflect(-directionalLight,unitNormal);
toCameraVector = (inverse(viewMatrix) * vec4(0.0,0.0,0.0,1.0)).xyz - worldPosition.xyz;
visibility = clamp(exp(-pow(length(positionRelativeToCam.xyz)*fogDensity,fogGradient)),0.0,1.0);
}
From (most recent) OpenGL Shading Language 4.60 Specification (HTML) - 4.3.9. Interface Blocks
A uniform or shader storage block array can only be indexed with a dynamically uniform integral expression, otherwise results are undefined.
block_id_out is fragment shader input (set by a vertex shader input) and not a Dynamically uniform expression. Hence blocks[block_id_out] is undefined and is not guaranteed, that blocks[i] becomes an active program resource.
I recommend to change the declaration. Do not create an array of uniforms. Create a single Uniform block:
const int MAX_BLOCKS = 16;
struct Block
{
vec4 color;
float shineDamper;
float reflectivity;
};
layout(std140) uniform Blocks
{
Block blocks[MAX_BLOCKS];
};
You have to create a Uniform Buffer Object to bind data to the uniform block.
I think that #Rabbid76 answer is correct, but I found a more satisfying workaround. I defined the struct and the uniform in the vertex shader, and then pass the correct values for color, shinedamper and reflectivity to the fragment shader. This makes more sense since I only want to access the values for each vertex and they are going to be same in the fragment shader, so doing it 3 times for each triangle is better than doing it hundreds of times for each pixel.
I am working on shadows for a Minecraft shader, and im stuck at trying to resolve the following error.
21:51:27.725
[Shaders] Error compiling fragment shader: /shaders/composite.fsh
21:51:27.726
[Shaders] Shader info log: /shaders/composite.fsh
0(84) : error C7623: implicit narrowing of type from "vec4" to "float"
21:51:27.727
[Shaders] Error linking program: 10 (composite)
I know the error is caused by incompatible types, but I'm still not sure how to solve it, so any help is appreciated.
#version 120
const int shadowMapResolution = 2048;
const float shadowDistance = 128;
const float shadowMapBias = 0.85;
const int noiseTextureResolution = 256;
#define SHADOWMAP_BIAS 0.85
uniform sampler2D colortex0;
uniform sampler2D shadowtex0;
uniform sampler2D shadowcolor0;
uniform sampler2D depthtex1;
uniform sampler2D noisetex;
uniform vec3 cameraPosition;
uniform mat4 gbufferModelViewInverse;
uniform mat4 gbufferModelView;
uniform mat4 shadowProjection;
uniform mat4 gbufferProjection;
uniform mat4 gbufferProjectionInverse;
uniform mat4 shadowModelView;
uniform float viewWidth;
uniform float viewHeight;
varying vec4 texcoord;
float depth = 0.5;
vec4 getCameraPosition(in vec2 coord)
{
float getdepth = depth;
vec4 positionNdcSpace = vec4(coord.s * 2.0 - 1.0, coord.t * 2.0 - 1.0, 2.0 * getdepth - 1.0, 1.0);
vec4 positionCameraSpace = gbufferProjectionInverse * positionNdcSpace;
return positionCameraSpace / positionCameraSpace.w;
}
vec4 getWorldSpacePosition(in vec2 coord)
{
vec4 cameraPos = getCameraPosition(coord);
vec4 worldPos = gbufferModelViewInverse * cameraPos;
worldPos.xyz += cameraPosition;
return worldPos;
}
vec3 getShadowSpacePosition(in vec2 coord)
{
vec4 worldSpacePos = getWorldSpacePosition(coord);
worldSpacePos.xyz -= cameraPosition;
vec4 shadowSpacePos = shadowModelView * worldSpacePos;
shadowSpacePos = shadowProjection * shadowSpacePos;
return shadowSpacePos.xyz * 0.5 + 0.5;
}
mat2 getRotationMatrix(in vec2 coord)
{
float rotationAmount = texture2D(
noisetex,
coord * vec2(
viewWidth / noiseTextureResolution,
viewHeight / noiseTextureResolution
)
).r;
return mat2(
cos(rotationAmount), -sin(rotationAmount),
sin(rotationAmount), cos(rotationAmount)
);
}
vec3 getShadows(in vec2 coord)
{
vec3 shadowCoord = getShadowSpacePosition(coord);
mat2 rotationMatrix = getRotationMatrix(coord);
vec3 shadowCol = vec3(0.0);
for (int i = 0; i < 32; i++)
{
vec2 offset = vec2(32 / shadowMapResolution);
offset = rotationMatrix * offset;
float shadowMapSample = texture2D(shadowtex0, shadowCoord.st + offset);
float visibility = step(shadowCoord.z - shadowMapSample, 0.001);
vec3 dayCol = vec3(1.0);
vec3 colorSample = texture2D(shadowcolor0, shadowCoord.st + offset).rgb;
shadowCol += mix(colorSample, dayCol, visibility);
}
return vec3(shadowCol) / 32;
}
vec3 calculateLighting(in vec3 color)
{
vec3 sunLight = getShadows(texcoord.st);
vec3 ambientLight = vec3(0.5, 0.7, 1.0) * 0.5;
return color * (sunLight + ambientLight);
}
void main()
{
depth = texture2D(depthtex1, texcoord.st).r;
vec3 color = texture2D(colortex0, texcoord.st).rbg;
color = calculateLighting(color);
gl_FragData[0] = vec4(color, 1.0);
gl_FragData[1] = vec4(depth);
}
The problem is that texture2D returns a vec4, but you are treating as a float. Read the red component instead
float shadowMapSample = texture2D(shadowtex0, shadowCoord.st + offset).r;
in my recent project I am working with hardware side tessellation. The pipeline I want to implement should take a low poly mesh, tessellate it and apply a displacement map.
The Tessellation works fine and just as I expected it to look like. However, when I apply the displacement map in the tessellation evaluation shader I get an output which is somewhat random.
This is the output without displacement (I used the heightmap as a texture to verify whether my texCoords are accurate)
This is what I get when I enable my displacement (using the same texture for both coloring and displacement):
The shader code is as follows:
//VERTEX SHADER
#version 430
layout(location = 0) in vec4 vertex;
layout(location = 1) in vec4 normal;
layout(location = 2) in vec2 texCoord;
out vec3 vPosition;
out vec3 vNormal;
out vec2 vTexCoord;
void main() {
vPosition = vertex.xyz;
vNormal = normal.xyz;
vTexCoord = texCoord;
}
//TESS CONTROL
#version 430
layout(vertices = 3) out;
in vec3 vPosition[];
in vec3 vNormal[];
in vec2 vTexCoord[];
out vec3 tcPosition[];
out vec3 tcNormal[];
out vec2 tcTexCoord[];
uniform float innerTessLevel;
uniform float outerTessLevel;
void main(){
float inTess = innerTessLevel;
float outTess = outerTessLevel;
tcPosition[gl_InvocationID] = vPosition[gl_InvocationID];
tcNormal[gl_InvocationID] = vNormal[gl_InvocationID];
tcTexCoord[gl_InvocationID] = vTexCoord[gl_InvocationID];
if(gl_InvocationID == 0) {
gl_TessLevelInner[0] = inTess;
gl_TessLevelInner[1] = inTess;
gl_TessLevelOuter[0] = outTess;
gl_TessLevelOuter[1] = outTess;
gl_TessLevelOuter[2] = outTess;
gl_TessLevelOuter[3] = outTess;
}
}
//TESS EVAL
#version 430
layout(triangles, equal_spacing, ccw) in;
in vec3 tcPosition[];
in vec3 tcNormal[];
in vec2 tcTexCoord[];
out vec3 tePosition;
out vec2 teTexCoord;
uniform mat4 ModelViewProjection;
uniform mat4 ModelView;
uniform sampler2D texHeight;
void main(){
vec3 p0 = gl_TessCoord.x * tcPosition[0];
vec3 p1 = gl_TessCoord.y * tcPosition[1];
vec3 p2 = gl_TessCoord.z * tcPosition[2];
vec3 pos = p0 + p1 + p2;
vec3 n0 = gl_TessCoord.x * tcNormal[0];
vec3 n1 = gl_TessCoord.y * tcNormal[1];
vec3 n2 = gl_TessCoord.z * tcNormal[2];
vec3 normal = normalize(n0 + n1 + n2);
vec2 tc0 = gl_TessCoord.x * tcTexCoord[0];
vec2 tc1 = gl_TessCoord.y * tcTexCoord[1];
vec2 tc2 = gl_TessCoord.z * tcTexCoord[2];
teTexCoord = tc0 + tc1 + tc2;
float height = texture(texHeight, teTexCoord).x;
pos += normal * (height * 0.2f);
gl_Position = ModelViewProjection * vec4(pos, 1);
tePosition = vec3(ModelView * vec4(pos,1.0)).xyz;
}
//GEOMETRY
#version 430
layout(triangles) in;
layout(triangle_strip, max_vertices = 3) out;
uniform mat4 ModelView;
in vec3 tePosition[3];
in vec3 tePatchDistance[3];
in vec2 teTexCoord[3];
out vec3 gFacetNormal;
out vec2 gTexCoord;
void main() {
vec3 A = tePosition[2] - tePosition[0];
vec3 B = tePosition[1] - tePosition[0];
vec4 N = vec4( normalize(cross(A, B)) , 0.0);
gFacetNormal = N.xyz;
gTexCoord = teTexCoord[0];
gl_Position = gl_in[0].gl_Position; EmitVertex();
gTexCoord = teTexCoord[1];
gl_Position = gl_in[1].gl_Position; EmitVertex();
gTexCoord = teTexCoord[2];
gl_Position = gl_in[2].gl_Position; EmitVertex();
EndPrimitive();
}
//FRAGMENT
#version 430
layout(location = 0) out vec4 fragColor;
in vec3 gFacetNormal;
in vec2 gTexCoord;
uniform float lit;
uniform vec3 light;
uniform sampler2D texHeight;
void main() {
#ifndef ORANGE_PURPLE
vec3 color = gl_FrontFacing ? vec3(1.0,0.0,0.0) : vec3(0.0,0.0,1.0);
#else
vec3 color = gl_FrontFacing ? vec3(1.0,0.6,0.0) : vec3(0.6,0.0,1.0);
#endif
if (lit > 0.5) {
color = texture(texHeight, gTexCoord).xyz;
vec3 N = normalize(gFacetNormal);
vec3 L = light;
float df = abs(dot(N,L));
color = df * color;
fragColor = vec4(color,1.0);
}
else {
fragColor = vec4(color,1.0);
}
}
It would be nice if someone could help me on that one.
Thanks to #AndonM.Coleman I solved the matter
In fact: the output gFacetNormal is only defined for your first vertex in the geometry shader. Outputs have to be set after every EmitVertex (...) as-per the GLSL specification, or they will be undefined. Many implementations re-use the last value set, but you cannot rely on that behavior if you want this to work portably. You need to set gFacetNormal once before every EmitVertex. void EmitVertex () - "Emits the current values of output variables to the current output primitive. On return from this call, the values of output variables are undefined."
Stupid of me not to notice that, but here is the working code:
//VERTEX
#version 430
layout(location = 0) in vec4 vertex;
layout(location = 1) in vec4 normal;
layout(location = 2) in vec2 texCoord;
out vec3 vPosition;
out vec3 vNormal;
out vec2 vTexCoord;
void main() {
vPosition = vertex.xyz;
vNormal = normal.xyz;
vTexCoord = texCoord;
}
//TESSELLATION CONTROL
#version 430
layout(vertices = 3) out;
in vec3 vPosition[];
in vec3 vNormal[];
in vec2 vTexCoord[];
out vec3 tcPosition[];
out vec3 tcNormal[];
out vec2 tcTexCoord[];
uniform float innerTessLevel;
uniform float outerTessLevel;
void main(){
float inTess = innerTessLevel;
float outTess = outerTessLevel;
tcPosition[gl_InvocationID] = vPosition[gl_InvocationID];
tcNormal[gl_InvocationID] = vNormal[gl_InvocationID];
tcTexCoord[gl_InvocationID] = vTexCoord[gl_InvocationID];
if(gl_InvocationID == 0) {
gl_TessLevelInner[0] = inTess;
gl_TessLevelInner[1] = inTess;
gl_TessLevelOuter[0] = outTess;
gl_TessLevelOuter[1] = outTess;
gl_TessLevelOuter[2] = outTess;
gl_TessLevelOuter[3] = outTess;
}
}
//TESSELLATION EVALUATION
#version 430
layout(triangles, equal_spacing, ccw) in;
in vec3 tcPosition[];
in vec3 tcNormal[];
in vec2 tcTexCoord[];
out vec3 tePosition;
out vec2 teTexCoord;
out vec3 teNormal;
uniform mat4 ModelViewProjection;
uniform mat4 ModelView;
uniform sampler2D texHeight;
void main(){
vec3 p0 = gl_TessCoord.x * tcPosition[0];
vec3 p1 = gl_TessCoord.y * tcPosition[1];
vec3 p2 = gl_TessCoord.z * tcPosition[2];
vec3 pos = p0 + p1 + p2;
vec3 n0 = gl_TessCoord.x * tcNormal[0];
vec3 n1 = gl_TessCoord.y * tcNormal[1];
vec3 n2 = gl_TessCoord.z * tcNormal[2];
vec3 normal = normalize(n0 + n1 + n2);
vec2 tc0 = gl_TessCoord.x * tcTexCoord[0];
vec2 tc1 = gl_TessCoord.y * tcTexCoord[1];
vec2 tc2 = gl_TessCoord.z * tcTexCoord[2];
teTexCoord = tc0 + tc1 + tc2;
float height = texture(texHeight, teTexCoord).x;
pos += normal * (height * 0.5f);
gl_Position = ModelViewProjection * vec4(pos, 1);
teNormal = vec3(ModelView * vec4(normal,0.0)).xyz;
tePosition = vec3(ModelView * vec4(pos,1.0)).xyz;
}
//GEOMETRY
#version 430
layout(triangles) in;
layout(triangle_strip, max_vertices = 3) out;
uniform mat4 ModelView;
in vec3 tePosition[3];
in vec2 teTexCoord[3];
in vec3 teNormal[3];
out vec3 gFacetNormal;
out vec2 gTexCoord;
void main() {
gFacetNormal = teNormal[0];
gTexCoord = teTexCoord[0];
gl_Position = gl_in[0].gl_Position; EmitVertex();
gFacetNormal = teNormal[1];
gTexCoord = teTexCoord[1];
gl_Position = gl_in[1].gl_Position; EmitVertex();
gFacetNormal = teNormal[2];
gTexCoord = teTexCoord[2];
gl_Position = gl_in[2].gl_Position; EmitVertex();
EndPrimitive();
}
//FRAGMENT
#version 430
layout(location = 0) out vec4 fragColor;
in vec3 gFacetNormal;
in vec2 gTexCoord;
uniform float lit;
uniform vec3 light;
uniform sampler2D texHeight;
void main() {
#ifndef ORANGE_PURPLE
vec3 color = gl_FrontFacing ? vec3(1.0,0.0,0.0) : vec3(0.0,0.0,1.0);
#else
vec3 color = gl_FrontFacing ? vec3(1.0,0.6,0.0) : vec3(0.6,0.0,1.0);
#endif
if (lit > 0.5) {
color = texture(texHeight, gTexCoord).xyz;
vec3 N = normalize(gFacetNormal);
vec3 L = light;
float df = abs(dot(N,L));
color = df * color;
fragColor = vec4(color,1.0);
}
else {
fragColor = vec4(color,1.0);
}
}