Im making a 2D side scroller game and I am currently implementing lights. The lights are just a light gradient texture rendered on top of the terrain multiplied to make it brighten up the area. However, I dont know how to nor understand how to do Ambient lighting. The following picture sums up what I have and the bottom part is what I want.
I am open to answers regarding shaders for I know how to use them.
I ended up creating an FBO texture the size of the screen, clearing it with the color of the ambience and drawing in all nearby lights. Then, I passed it through a shader I made which takes in 2 textures for uniforms. The texture to draw and the light FBO itself. The shader multiplies the textures being drawn with the FBO and it came out nicely.
ambience.frag
uniform sampler2D texture1;
uniform sampler2D texture2;
varying vec2 texCoord;
void main( void ) {
vec4 color1 = vec4(texture2D(texture1, gl_TexCoord[0].st));
vec4 color2 = vec4(texture2D(texture2, texCoord));
gl_FragColor = color1*vec4(color2.r,color2.g,color2.b,1.0);
}
ambience.vs
varying vec2 texCoord;
uniform vec2 screen;
uniform vec2 camera;
void main(){
gl_Position = ftransform();
gl_TexCoord[0] = gl_MultiTexCoord0;
vec2 temp = vec2(gl_Vertex.x,gl_Vertex.y)-camera;
texCoord = temp/screen;
}
Related
I have several objects without texture coordinates UV passed into the fragment shader, and i only have two other objects with texture coordinates UV passed into the fragment shader. The objects without texture were still visible but with a dull color. But after plugging in the light equations it becomes black and non-visible. How do i draw the non-texturized objects without changing it's original color and also keeping the light equation (i've already created color arrays for them and passed them into the vertex shader). I've tried this but my fragment shader wouldn't compile.
#version 330
in vec3 fragmentColor;
in vec3 fragmentNormal;
in vec2 UV;
in vec4 Position;
uniform vec4 lighteye;
uniform float intensityh;
uniform float intensityd;
uniform float objectd;
uniform vec4 worldCoord;
// Data for the texture
uniform sampler2D texture_Colors;
if(UV.x >= 0.0)
color = intensityh * texture2D( texture_Colors, UV ).rgb * diffuse + (intensityd * texture2D( texture_Colors, UV ).rgb * something) ;
else
color = vec4(fragmentColor,1.0);
As far as I understood, you could do something like this:
color r = intensityh * texture2D( texture_Colours, worldCoord.xy).rgb * diffuse+( intensityd* texture2D (texture_Colours, worldCoord.xy).rgb * something
This should texture your objects based on their position in the 3D space. Don't forget, however, to enable texture repeating by CPU code for each texture, like this:
glTexParameterf(GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameterf(GL_TEXTURE_WRAP_T, GL_REPEAT);
I have been trying to implement a heightmap to my terrain shader, but the terrain remains flat. The texture is properly loaded in the vertex shader, and I try to use the greyscale values of the texture based on the mesh's uvs to adjust the vertex height:
//DIFFUSE VERTEX SHADER
#version 330
uniform mat4 projectionMatrix;
uniform mat4 viewMatrix;
uniform mat4 modelMatrix;
in vec3 vertex;
in vec3 normal;
in vec2 uv;
uniform sampler2D heightmap;
out vec2 texCoord;
void main( void ){
vec3 _vertex = vertex;
_vertex.y = texture(heightmap, uv).r * 2.f;
gl_Position = projectionMatrix * viewMatrix * modelMatrix * vec4(_vertex, 1.f);
texCoord = uv;
}
Fragment: (the splatmap works so ignore that)
uniform sampler2D splatmap;
uniform sampler2D diffuse1;
uniform sampler2D diffuse2;
uniform sampler2D diffuse3;
uniform sampler2D diffuse4;
in vec2 texCoord;
out vec4 fragment_color;
void main( void ) {
///Loading the splatmap and the diffuse textures
vec4 splatTexture = texture2D(splatmap, texCoord);
vec4 diffuseTexture1 = texture2D(diffuse1, texCoord);
vec4 diffuseTexture2 = texture2D(diffuse2, texCoord);
vec4 diffuseTexture3 = texture2D(diffuse3, texCoord);
vec4 diffuseTexture4 = texture2D(diffuse4, texCoord);
//Interpolate between the different textures using the splatmap's rgb values (works)
diffuseTexture1 *= splatTexture.r;
diffuseTexture2 = mix (diffuseTexture1, diffuseTexture2, splatTexture.g);
diffuseTexture3 = mix (diffuseTexture2,diffuseTexture3, splatTexture.b);
vec4 outcolor = mix (diffuseTexture3, diffuseTexture4, splatTexture.a);
fragment_color = outcolor;
}
Some additional info:
All textures are loaded like this in my terrain material and passed to the shader (works properly):
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, heightMap->getId());
glUniform1i (_shader->getUniformLocation("heightMap"),0);
...
The plane mesh uvs are mapped like this:
(0,1) (1,1)
(0,0) (1,0)
I guess I am doing something horribly wrong, but I can't figure out what. Any help is appreciated!
Does your writing this:
The plane mesh uvs are mapped like this:
(0,1) (1,1)
(0,0) (1,0)
… mean that your mesh consists of just 4 vertices? If so, then that's your problem right there: The Vertex shader can not magically create "new" vertices, so your heightmap texture is sampled at only 4 points (and nothing in between).
And because you sample the texture coordinates at integer values and your texture coordinates and are at 0 and 1, you're effectively sampling the very same texture coordinate, so you're going to see the same displacement for all four vertices.
Solution: Tesselate your base mesh so that there are actually vertices available to displace. A tesselation shader is perfectly fine for that.
EDIT:
BTW, you can simplyfiy your vertex shader a bit: For the attributes make it a
in vec2 vertex;
which requires just 2/3 of the space of vec3, since you're not using the z component anyway.
float y = texture(heightmap, uv).r * 2.f;
gl_Position =
projectionMatrix
* viewMatrix
* modelMatrix
* vec4(vertex.x, y, vertex.y, 1.f);
I have a cube map set up and what I want to do next is to mark/show separately which areas/segments of the textures on each face of the cube map is being rendered (depending on the camera).
For example, here is my basic vertex shader:
#version 400
in vec3 vp;
uniform mat4 P, V;
out vec3 texcoords;
vec3 newP;
void main () {
texcoords = vp;
gl_Position = P * V * vec4 (vp, 1.0);
}
and here is my basic fragment shader:
#version 400
in vec3 texcoords;
uniform samplerCube cube_texture;
out vec4 frag_colour;
void main () {
frag_colour = texture (cube_texture, texcoords);
}
I now want to show the unfolded 6 textures of a cubemap and color overlay the areas the camera was looking at in the cube-map, for each texture.
Example, if my camera is viewing the intersection of the left and back sides of the cube, I want a separate display where the I can see the 6 side textures unfolded and the area of the respective textures, the camera was viewing, highlighted (half of the loaded texture for the left wall and half of the loaded texture for the back wall)
Can I get some heads up on how to implement this? Or if someone has some similar code in OpenGl.
Thanks :)
I'm working on shadows for a 2D overhead game. Right now, the shadows are just sprites with the color (0,0,0,0.1) drawn on a layer above the tiles.
The problem: When many entities or trees get clumped together, the shadows overlap, forming unnatural-looking dark areas.
I've tried drawing the shadows to a framebuffer and using a simple shader to prevent overlapping, but that lead to other problems, including layering issues.
Is it possible to enable a certain blend function for the shadows that prevents "stacking", or a better way to use a shader?
If you don't want to deal with sorting issues, I think you could do this with a shader. But every object will have to be either affected by shadow or not. So tall trees could be marked as not shadow receiving, while the ground, grass, and characters would be shadow receiving.
First make a frame buffer with clear color white. Draw all your shadows on it as pure black.
Then make a shadow mapping shader to draw everything in your world. This relies on you not needing all four channels of the sprite's color, because we need one of those channels to mark each sprite as shadow receiving or not. For example, if you aren't using RGB to tint your sprites, we could use the R channel. Or if you aren't fading them in and out, we could use A. I'll assume the latter here:
Vertex shader:
attribute vec4 a_position;
attribute vec4 a_color;
attribute vec2 a_texCoord0;
varying vec2 v_texCoords;
varying vec2 v_texCoordsShadowmap;
varying vec4 v_color;
uniform mat4 u_projTrans;
void main()
{
v_texCoords = a_texCoord0;
v_color = a_color;
v_color.a = v_color.a * (255.0/254.0); //this is a correction due to color float precision (see SpriteBatch's default shader)
vec3 screenPosition = u_projTrans * a_position;
v_texCoordsShadowmap = (screenPosition.xy * 0.5) + 0.5;
gl_Position = screenPosition;
}
Fragment shader:
#ifdef GL_ES
precision mediump float;
#endif
varying vec2 v_texCoords;
varying vec2 v_texCoordsShadowmap;
varying vec4 v_color;
uniform sampler2D u_texture;
uniform sampler2D u_textureShadowmap;
void main()
{
vec4 textureColor = texture2D(u_texture, v_texCoords);
float shadowColor = texture2D(u_textureShadowmap, v_texCoordsShadowmap).r;
shadowColor = mix(shadowColor, 1.0, v_color.a);
textureColor.rgb *= shadowColor * v_color.rgb;
gl_FragColor = textureColor;
}
These are completely untested and probably have bugs. Make sure you assign the frame buffer's color texture to "u_textureShadowmap". And for all your sprites, set their color's alpha based on how much shadow you want them to have cast on them, which will generally always be 0 or 0.1 (based on the brightness you were using before).
Draw your shadows to fbo with disabled blending.
Draw background e.g. grass
Draw shadows texture from fbo
Draw all other sprites
There are two textures that I have to display and they overlap. one of the textures have alpha channel, so it is possible to blend it. However, since the texture coordinates are clumped together, I decided to scale them. gl_TexCoord[0] = gl_MultiTexCoord0*2.0;
This does not quite work, because, it sclaes the alpha channel as well. How do I scale the texture coordinates, but keep the alpha channel value the same?
Below are the GLSL shaders.
vertex shader:
void main()
{
gl_TexCoord[0] = gl_MultiTexCoord0*2.0; //this is where I scale the texture
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
}
fragment shader:
uniform sampler2D textureSample_0;
uniform sampler2D textureSample_1;
void main()
{
vec4 grass=texture2D(textureSample_1, gl_TexCoord[0].st);
vec4 sand = texture2D(textureSample_0, gl_TexCoord[0].st);
gl_FragColor = grass*grass.a+sand*(1.0-grass.a); //alpha channel is also scaled here
}
Any help would be appreciated.