about VTF(vertex texture fetch) - opengl

I'm studying clipmap algorithm, and I want to get elevations by VTF.
But I've got a problem when using vertex textures. I don't know what's wrong.
the related code is like this:
int width=127;
float *data=new float[width*width];
for(int i=0;i<width*width;i++)
data[i]=float(rand()%100)/100.0;
glGenTextures(1, &vertexTexture);
//glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, vertexTexture);
//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,GL_NEAREST_MIPMAP_NEAREST);
glTexImage2D(
GL_TEXTURE_2D, 0, GL_LUMINANCE_FLOAT32_ATI,
width, width, 0, GL_LUMINANCE, GL_FLOAT, data);
the GLSL code in vertex shader is like this:
#version 410
uniform mat4 mvpMatrix;
uniform sampler2D vertexTexture;
in vec2 vVertex;
void main(void)
{
vec2 vTexCoords=vVertex/127.0;
float height = texture2DLod(vertexTexture, vTexCoords,0.0).x*100.0;
// I also tried texture2D(vertexTexture, vTexCoords)
// and texture(vertexTexture, vTexCoords),but they don't work.
vec4 position=vec4(vVertex.x,height,vVertex.y,1.0);
gl_Position = mvpMatrix * position;
}
I store some random floats in array data then store them with a texture,and as the vertex shader showing,I want to get some values to the y coordinate by VTF.but the result is that the height is always 0.I think something must be wrong. I don't know what's wrong and how to do it the right way.

it's solved now.the answer is here.thank you all!
Try setting the texture's minification filter to GL_NEAREST or GL_LINEAR after glTexImage2D():
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
The OpenGL default is to use mipmaps and you didn't send any which makes the texture incomplete and will disable that texture image unit.
Then you can use texture(vertexTexture, vTexCoords) inside the shader instead of the deprecated texture2DLOD() version with the explicit LOD access.

Related

Sampling 3D texture to get a 2D image

I have a scalar field of values which I have mapped to a 3D texture( image_texture ). And then given a plane gPlaneParams , I have to render the texture of the scalar-field along it.
What I'm doing:
I send 4 points which span the window dimensions using two triangles to the shaders. I bind the texture using a sampler in the fragment shader. Below is the fragment shader code.
#version 330 core
uniform sampler3D text_sampler;
uniform vec4 gPlaneParams;
in vec4 inPos;
void main()
{
vec4 Pos = inPos;
// position input is a square[-1,1]^2
// and needs to be mapped the plane ax+by+cz=d, where a,b,c,d are the plane parameters;
//where x,y,z belongs to [0,1]^3
if (gPlaneParams.z!=0){
Pos.z = (gPlaneParams.w - gPlaneParams.x*Pos.x - gPlaneParams.y*Pos.y)/gPlaneParams.z;
}
else{
if (gPlaneParams.x!=0){
Pos.z=Pos.x;
Pos.x = (gPlaneParams.w - gPlaneParams.y*Pos.y - gPlaneParams.z*Pos.z)/gPlaneParams.x;
}
else if (gPlaneParams.y!=0){
Pos.z=Pos.y;
Pos.y = (gPlaneParams.w - gPlaneParams.x*Pos.x - gPlaneParams.z*Pos.z)/gPlaneParams.y;
}
}
gl_FragColor=vec4(1.0,0,0,0)*texture3D(text_sampler,(Pos.xyz+1)/2);
}
In my C++ code, I bind the texture as follows:
glGenTextures(1,textureID);
glBindTexture(GL_TEXTURE_3D,textureID[0]);
glTexImage3D(GL_TEXTURE_3D, 0, GL_RGB,object_size[0],object_size[1],object_size[2], 0, GL_RGB, GL_UNSIGNED_INT, image_texture1);
glTexParameterf(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_3D,GL_TEXTURE_WRAP_R,GL_CLAMP_TO_EDGE);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_3D,textureID[0]);
bool err=glIsTexture(textureID[0]);
cout<<"Texture bound?"<<err<<endl;
Unfortunately, this does not render any output. Can someone help me figure out what I'm doing wrong?
I have done everything else correctly
The 4 Vertices and 2 triangles are properly bound (I can render them by giving them constant colours)
The image texture is contiguous in memory image_texture = (unsigned int*) malloc(object_size[0] *object_size[1] *object_size[2]*3* sizeof(unsigned int));
All my inputs to the shader are successfully bound.:
gSamplerLocation = glGetUniformLocation(ShaderProgram, "text_sampler");
gPLaneLoc = glGetUniformLocation(ShaderProgram, "gPlaneParams");
glUniform1i(gSamplerLocation, 0);
glUniform4f(gPLaneLoc,plane_params[0],plane_params[1],plane_params[2],plane_params[3]);

Opengl/glsl : Pass float array to shader by texture

I am trying to pass a float* that contains 128*128 float to a shader. Since this array is too big, I am trying to pass by a texture to get my float* in my shader. The problem is I don't know how to use this array inside my shader.
I print my float* before sending it to my shader, and It contains number between -1 and 1.
My goal is to simulate waves on water with perlin noise, so my array of float is perlin noises.
So I instantiate my noise texture like this :
_perlin_noise = new float[_dimension * _dimension];
//... I put float inside my _perlin_noise variable
//Then I instantiate my texture :
glGenTextures(1, &_perlin_noise_text);
glBindTexture(GL_TEXTURE_2D, _perlin_noise_text);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_R32F, _dimension, _dimension, 0,
GL_RED, GL_FLOAT, _perlin_noise);
glActiveTexture(0);
glBindTexture(GL_TEXTURE_2D, 0);
My water use two textures : One texture is full blue, the other is a texture of foam.
So now I have a third texture that is my perlin noise. And I want to ajust the height of my vertices by perlin noise.
So before anything, I alocate uniform variable to my shader like this :
main_water_shader->use();
glUniform1i(glGetUniformLocation(main_water_shader->getProgram(), "main_water_texture"), 0);
glUniform1i(glGetUniformLocation(main_water_shader->getProgram(), "foam_texture"), 1);
glUniform1i(glGetUniformLocation(main_water_shader->getProgram(), "perlin_noise"), 2);
Then I want to ajust vertices's height in my vertex shader, but I don't know how to do it. I tried to do that in my vertex shader :
uniform sampler2D perlin_noise;
//some other uniform...
void main()
{
//calculating vertex height
float height = float( texture2D(perlin_noise, vec2(x, y)) );
vec3 new_vertex_position = vertex_position;
new_vertex_position.y = height;
//Standard stuff
vs_position = vec4(ModelMatrix * vec4(new_vertex_position, 1.f)).xyz;
vs_texcoord = vec2(vertex_texcoord.x, vertex_texcoord.y );
vs_normal = mat3(ModelMatrix) * vertex_normal;
gl_Position = ProjectionMatrix * ViewMatrix * ModelMatrix * vec4(new_vertex_position, 1.f);
}
Nothing change, the height of my vertices is still the same. And if I try to display my perlin_noise texture in my fragment shader onto a plan, I get this :
You can see my plane (which is very large) with a black and white texture on it that is repeated. So I guess my perlin_noise texture does contains something (even if it is a bit weird), but I can't figure out how to use it in my vertex shader.
EDIT : In my screenshoot, I also use a vertex shader with height ajusted with perlin noise, but as you can see, my plane is plane, so It does not seems to work.
EDIT2 : If I'm not clear enough, tell me

OpenGL, blending transparent textures with object color

I can set my fragment shader to showing colors of the object or the texture color of the object. My question is, how can I combine those two so that I can have a transparrent picture with lines for bricks, and then show the different colors underneath, so that by changing the color of the object, you change the color of the bricks.
I tried using mix() for that in the fragment shader, but it only shows me the glClearColor where it is transparent insteath of the red color I have assigned it!
My fragment shader:
#version 120
uniform sampler2D diffuse;
varying vec3 shared_colors;
varying vec2 shared_texCoords;
void main() {
vec4 color = vec4(shared_colors, 1);
vec4 texture = texture2D(diffuse, shared_texCoords);
vec4 finalColor = vec4(mix(color.rgb, texture.rgb, 1), 1);
gl_FragColor = finalColor;
}
EDIT: Added texture loader func:
void Texture::createTexture(SDL_Surface *rawImage, GLenum format) {
//Convert to a texture of pure color pixels for OpenGL
SDL_Surface *image = SDL_CreateRGBSurface(NULL, rawImage->w, rawImage->h, 32, 0, 0, 0, 0);
SDL_BlitSurface(rawImage, NULL, image, NULL);
//Generate texture
glGenTextures(1, &m_texture);
//Tell OpenGL to use this texture
glBindTexture(GL_TEXTURE_2D, m_texture);
//Set texture parameters
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
//Generate texture from image
glTexImage2D(GL_TEXTURE_2D, 0, 4, image->w, image->h, 0, format, GL_UNSIGNED_BYTE, image->pixels);
m_dimension = new PixelSize(image->w, image->h);
//Free loaded images
SDL_FreeSurface(rawImage);
SDL_FreeSurface(image);
}
You should take a closer look at mix (...) to understand why using 1 for a effectively does nothing meaningful (it returns y).
Let us start by considering the usual alpha blending function: GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA.
This means to take the alpha channel of the source and multiply it by the source color (fragment color) and add that to the inverse of the alpha channel multiplied by the destination color (framebuffer).
  AlphaBlend = SrcRGBA * SrcA + DstRGBA * (1.0 - SrcA)
Now, if you look at the implementation of mix (...) it should look quite familiar:
  x * (1.0 - a) + y * a
Clearly, this is order dependent for any value of a != 0.5 (1.0 - 0.5 = 0.5) and more importantly in this case it completely throws out one of your colors if you use a value of 1.0 for a (as this multiplies x by 0.0).

Incorrect texture coordinate calculated for shadow map

I am having problems getting the correct texture coordinate to sample my shadow map. Looking at my code, the problem appears to be from incorrect matrices. This is the fragment shader for the rendering pass where I do shadows:
in vec2 st;
uniform sampler2D colorTexture;
uniform sampler2D normalTexture;
uniform sampler2D depthTexture;
uniform sampler2D shadowmapTexture;
uniform mat4 invProj;
uniform mat4 lightProj;
uniform vec3 lightPosition;
out vec3 color;
void main () {
vec3 clipSpaceCoords;
clipSpaceCoords.xy = st.xy * 2.0 - 1.0;
clipSpaceCoords.z = texture(depthTexture, st).x * 2.0 - 1.0;
vec4 position = invProj * vec4(clipSpaceCoords,1.0);
position.xyz /= position.w;
//At this point, position.xyz seems to be what it should be, the world space coordinates of the pixel. I know this because it works for lighting calculations.
vec4 lightSpace = lightProj * vec4(position.xyz,1.0);
//This line above is where I think things go wrong.
lightSpace.xyz /= lightSpace.w;
lightSpace.xyz = lightSpace.xyz * 0.5 + 0.5;
float lightDepth = texture(shadowmapTexture, lightSpace.xy).x;
//Right here lightDepth seems to be incorrect. The only explanation I can think of for this is if there is a problem in the above calculations leading to lightSpace.xy.
float shadowFactor = 1.0;
if(lightSpace.z > lightDepth+0.0005) {
shadowFactor = 0.2;
}
color = vec3(lightDepth);
}
I have removed all the code irrelevant to shadowing from this shader (Lighting, etc). This is the code I use to render the final pass:
glCullFace(GL_BACK);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
postShader->UseShader();
postShader->SetUniform1I("colorTexture", 0);
postShader->SetUniform1I("normalTexture", 1);
postShader->SetUniform1I("depthTexture", 2);
postShader->SetUniform1I("shadowmapTexture", 3);
//glm::vec3 cp = camera->GetPosition();
postShader->SetUniform4FV("invProj", glm::inverse(camera->GetCombinedProjectionView()));
postShader->SetUniform4FV("lightProj", lights[0].camera->GetCombinedProjectionView());
//Again, if I had to guess, these two lines above would be part of the problem.
postShader->SetUniform3F("lightPosition", lights[0].x, lights[0].y, lights[0].z);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, frameBuffer->GetColor());
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, frameBuffer->GetNormals());
glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_2D, frameBuffer->GetDepth());
glActiveTexture(GL_TEXTURE3);
glBindTexture(GL_TEXTURE_2D, lights[0].shadowmap->GetDepth());
this->BindPPQuad();
glDrawArrays(GL_TRIANGLES, 0, 6);
In case it is relevant to my problem, here is how I generate the depth framebuffer attachments for the depth and shadow maps:
void FrameBuffer::Init(int textureWidth, int textureHeight) {
glGenFramebuffers(1, &fbo);
glGenTextures(1, &depth);
glBindTexture(GL_TEXTURE_2D, depth);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, textureWidth, textureHeight, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depth, 0);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
Where is the problem in my math or my code, and what can I do to fix it?
After some experimentation, I have found that my problem does not lie in my matrices, but in my clamping. It seems that I get strange values when I use GL_CLAMP or GL_CLAMP_TO_EDGE, but I get almost correct values when I use GL_CLAMP_TO_BORDER. There are more problems, but they do not seem to be matrix related as I thought.

GLSL 150 GL 3.2 black textures

I can't get my textures to work, all the screen is black.
Here is my code for loading the images, I use lodepng:
std::vector<unsigned char> image;
unsigned int error = lodepng::decode(image, w, h, filename);
GLuint texture_id;
glGenTextures(1, &texture_id);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture_id);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, 4, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, &image[0]);
glBindTexture(GL_TEXTURE_2D, 0);
For the rendering I do this:
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture_id_from_above); //texture_id were checked, seemed fine
glUniform1i(shader_sampler_loc, GL_TEXTURE0);
and my frag shader(trimmed version) is basically doing this:
uniform sampler2D sampler;
void main(void) {
gl_FragColor = texture2D(sampler, uv_coord);
}
The UV-coordinates are fine, the vector from lodepng containes many elements and there is no error returned. To further pin the problem I tried this:
gl_FragColor = texture2D(sampler, uv_coord)*0.5 + vec4(1, 1, 1, 1)*0.5f
To see if the whole assignment is somehow skipped or the texture in fact black. As a result I still only get a black window. But by removing
glActiveTexture(GL_TEXTURE0); //x2, and
glUniform1i(sampler_loc, GL_TEXTURE0);
all my objects appear gray. I have no clue what is wrong.
BTW: it was working before moving to OpenGL 3.2 (had 2.1 before), and all images are ^2. I use CORE_PROFILE && FORWARD_COMPAT.
Vertex shader:
#version 150
//VBO vertex attributes
attribute vec3 pos;
attribute vec2 tex;
attribute vec3 normal;
varying vec2 uv_coord;
uniform mat4 mvp_mat;
void main(void) {
gl_Position = mvp_mat * vec4(pos, 1);
uv_coord = tex;
}
glUniform1i(shader_sampler_loc, GL_TEXTURE0);
. . . should be
glUniform1i(shader_sampler_loc, 0);
etc.
So I kind of solved it, by using OPENGL_COMPAT_PROFILE it works. Though I would really want to go full 3.2, and find which parts are deprecated...
EDIT:
In my case, I finally found the dumb error, I was using
glTexImage2D(GL_TEXTURE_2D, 0, 4, ... //instead of
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, ...
So I guess the with the old GL I was lucky, and with 3.2 the enum were changed?
As comments suggest try changing the following:
Vertex shader:
out instead of varying
Add layout(location = #) to your attributes and change attribute for in.
Make sure, number of locations match the code
Fragment shader: (Assuming since its not complete)
in instead of varying
Add layout(location = #) to your sampler uniform
For the code:
Change
glUniform1i(sampler_loc, GL_TEXTURE0)
to
glUniform1i(sampler_loc, 0)