🎉 Celebrating 25 Years of GameDev.net! 🎉

Not many can claim 25 years on the Internet! Join us in celebrating this milestone. Learn more about our history, and thank you for being a part of our community!

OpenGL 4 reflections

Started by
110 comments, last by taby 1 year, 7 months ago

Tada!

Advertisement

Now… how to do glossy reflections.

taby said:
Now… how to do glossy reflections.

Blur in images space, similar to the DOF you did.
So you want the distance from shading point to reflected surface to set the filter radius, and you may want to mask out pixels which have no reflections from the filter kernel.

I have one problem. I tried raising parts of the board. Now there are parts of the image that should not be reflected. Any ideas on how to set those pixels to non-reflective.

I tried all kinds of things…. Here is the vertex shader at this point in time:

#version 430 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aNormal;
layout (location = 2) in vec2 aTexCoords;

out vec2 TexCoords;

out VS_OUT {
    vec3 FragPos;
    vec3 Normal;
    vec2 TexCoords;
    vec3 mvPosition;
    vec3 untransformed_normal;
} vs_out;

uniform mat4 projection;
uniform mat4 view;
uniform mat4 model;

uniform bool reverse_normals = false;

void main()
{
    vs_out.untransformed_normal = aNormal;


    mat4 mv = view * model;
    mat4 mvp = projection * view * model;


    vs_out.mvPosition = (mv * vec4(aPos,1.0)).xyz;

    vs_out.FragPos = vec3(model * vec4(aPos, 1.0));
    if(reverse_normals) // a slight hack to make sure the outer large cube displays lighting from the 'inside' instead of the default 'outside'.
        vs_out.Normal = transpose(inverse(mat3(model))) * (-1.0 * aNormal);
    else
        vs_out.Normal = transpose(inverse(mat3(model))) * aNormal;
    vs_out.TexCoords = aTexCoords;
    gl_Position = projection * view * model * vec4(aPos, 1.0);
}

Here's the fragment shader, where I do the checking:

#version 430 core
out vec4 FragColor;

in VS_OUT{
	vec3 FragPos;
	vec3 Normal;
	vec2 TexCoords;
	vec3 mvPosition;
	vec3 untransformed_normal;
} fs_in;




const int max_num_lights = 4;

uniform sampler2D diffuseTexture;
uniform sampler2D specularTexture;

uniform samplerCube depthMaps[max_num_lights];

uniform vec3 lightPositions[max_num_lights];
uniform vec3 lightColours[max_num_lights];
uniform int lightEnabled[max_num_lights];








uniform vec3 viewPos;

uniform float far_plane;
uniform int shadows = 1;
uniform int flat_draw = 0;
uniform vec3 flat_colour;


uniform int specular_only = 0;


vec3 MaterialKd = vec3(1.0, 1.0, 1.0);
vec3 MaterialKs = vec3(1.0, 0.5, 0.0);
vec3 MaterialKa = vec3(0.0, 0.025, 0.075);
float MaterialShininess = 1;



vec3 phongModelDiffAndSpec(bool do_specular, vec3 lp, int index)
{
	vec3 n = fs_in.Normal;
	vec3 s_light1 = normalize(vec3(lp.xyz) - fs_in.mvPosition);

	vec3 v = normalize(-fs_in.mvPosition.xyz);
	vec3 r_light1 = reflect(-s_light1, n);

	float sDotN_light1 = max(dot(s_light1, n), 0.0);

	vec3 diffuse_light1 = lightColours[index] * texture(diffuseTexture, fs_in.TexCoords).rgb * sDotN_light1;

	vec3 spec_light1 = vec3(0.0);

	if (sDotN_light1 > 0.0)
	{
		spec_light1.x = MaterialKs.x * pow(max(dot(r_light1, v), 0.0), MaterialShininess);
		spec_light1.y = MaterialKs.y * pow(max(dot(r_light1, v), 0.0), MaterialShininess);
		spec_light1.z = MaterialKs.z * pow(max(dot(r_light1, v), 0.0), MaterialShininess);
	}


	vec3 n2 = fs_in.Normal;

	vec3 s2_light1 = normalize(vec3(-lp) - fs_in.mvPosition);

	vec3 v2 = normalize(-fs_in.mvPosition.xyz);

	vec3 r2_light1 = reflect(-s2_light1, n2);



	float sDotN2_light1 = max(dot(s2_light1, n2) * 0.5f, 0.0);




	vec3 diffuse2_light1 = lightColours[index] * 0.25 * MaterialKa * sDotN2_light1;



	float k_light1 = (1.0 - sDotN_light1) / 2.0;



	vec3 ret_light1 = diffuse_light1 + diffuse2_light1 + MaterialKa * k_light1;

	if (do_specular)
	{
		ret_light1 = ret_light1 + spec_light1;
	}

	return (ret_light1);// + ret_light2);///2.0;
}





float get_shadow(vec3 lp, samplerCube dmap)
{
	// get vector between fragment position and light position
	vec3 fragToLight = fs_in.FragPos - lp;
	// ise the fragment to light vector to sample from the depth map    
	float closestDepth = texture(dmap, fragToLight).r;
	// it is currently in linear range between [0,1], let's re-transform it back to original depth value
	closestDepth *= far_plane;
	// now get current linear depth as the length between the fragment and light position
	float currentDepth = length(fragToLight);
	// test for shadows
	float bias = 0.05; // we use a much larger bias since depth is now in [near_plane, far_plane] range
	float shadow = currentDepth - bias > closestDepth ? 1.0 : 0.0;

	shadow = 1 - shadow;

	return shadow;

}



void main()
{
	if(specular_only == 1)
	{
		FragColor = texture(specularTexture, fs_in.TexCoords);
		
		vec3 n =  fs_in.untransformed_normal;
		vec3 n2 = fs_in.FragPos - vec3(0, 0 , 0); // Use this as an example position

		if(dot(n, n2) < 0)
			FragColor = vec4(0, 0, 0, 1);
	
		return;
	}

	if(flat_draw == 1)
	{
		FragColor = vec4(flat_colour, 1.0);
		return;
	}

	MaterialKs *= texture(specularTexture, fs_in.TexCoords).rgb;


	int num_shadows = 0;

	for (int i = 0; i < max_num_lights; i++)
	{
		if (lightEnabled[i] == 0)
			continue;

		float s = get_shadow(lightPositions[i], depthMaps[i]);
		
		if(s == 0)
			num_shadows++;
	}

	vec3 diffAndSpec = vec3(0, 0, 0);





	if (num_shadows == 0)
	{
		for (int i = 0; i < max_num_lights; i++)
		{
			if (lightEnabled[i] == 0)
				continue;

			diffAndSpec += phongModelDiffAndSpec(true, lightPositions[i], i);
		}
	}
	else
	{
		for (int i = 0; i < max_num_lights; i++)
		{
			if (lightEnabled[i] == 0)
				continue;

			diffAndSpec += get_shadow(lightPositions[i], depthMaps[i]) * phongModelDiffAndSpec(false, lightPositions[i], i);
		}
	}
	
	FragColor = vec4(diffAndSpec, 1.0);
	FragColor = pow(FragColor, vec4(1.0 / 2.2));

	return;
}

The part in question is:

	if(specular_only == 1)
	{
		FragColor = texture(specularTexture, fs_in.TexCoords);
		
		vec3 n =  fs_in.untransformed_normal;
		vec3 n2 = fs_in.FragPos - vec3(0, 0 , 0); // Use this as an example position

		if(dot(n, n2) < 0)
			FragColor = vec4(0, 0, 0, 1);
	
		return;
	}

Fixed some bugs, and got the high-res screenshot function working.

Only one bug left!

I cheated and made only the lower level reflective.

taby said:
I cheated and made only the lower level reflective.

But then you'd need to add the upper levels to be reflected.

And you might want to blend the reflections by angle of view vector to surface normal. See the fresnel term of PBS theory for reference.

@JoeJ Let me think on that. I got blurred reflections sort of working.

Even better:

Very cool : )

Though, after the fix you now have a black halo instead a sharp cut off. Probably you can reject such ‘black’ samples from the accumulation,
either by setting their weight to zero (if you have weights), or by counting valid samples so you can divide by that count in the end to get the correct average.

This topic is closed to new replies.

Advertisement