I am seeing a strange issue with a multi pass, multi RT ping-pong render
I am using 3 shaders and an FBO, I get no errors at any stage. I am using opengl 4, so I am not using glBegin/glEnd, I use my own matrices for transformation and i am using vertex buffers for rendering
The general idea of this test is to render 3 different colours to three separate fbo attachments (I realise that it is not efficient rendering the vbo twice in the first pass but this is just to help me understand a problem in some other source) I then bind a separate set of textures to the fbo and use the first set as the samplers. The final pass is to blend the results into the back buffer
What is odd is that the output is both quads appear red, when the first should be red and the second green (as these values come from the second shader).
If i change the function SamplePix in the second shader to always take from the second sampler both appear green, and if lookups up from the third then all appears yellow, but it seems to only read from one.
For now I can't seem to explain why I can read from each sampler ok but the loop doesn't seem to lookup correctly (in shader 2)
Also if I switch to rendering the texture sampled in shader 2 i see a black quad in the second pass (image 2)
Hopefully someone can throw some light on the problem. (I have also tried adding a sync fence object after the first pass but this didn't make a difference)
Texture Sample:
// initial setup of shaders and vertex buffers ommitted for now (in separate source files)
// fbo setup like so
const int DepthLayers = 3;
bool InitFBO()
{
// width and height 768pixels
for (int j=0; j<DepthLayers; j++)
{
const int idx = j + (DepthLayers*i);
glGenTextures(1, &g_FBOManager.m_fboTex[ idx ]);
glBindTexture(GL_TEXTURE_2D, g_FBOManager.m_fboTex[ idx ]);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
//no mipmaps
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, g_XMLSettings->WWidth(), g_XMLSettings->WHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
//depth
glGenTextures(1, &g_FBOManager.m_fboDepthTex[ idx ]);
glBindTexture(GL_TEXTURE_2D, g_FBOManager.m_fboDepthTex[ idx ]);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
//no mipmaps
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE, GL_INTENSITY);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE/* GL_COMPARE_R_TO_TEXTURE*/);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
glTexImage2D( GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32, g_XMLSettings->WWidth(), g_XMLSettings->WHeight(), 0, GL_DEPTH_COMPONENT, GL_FLOAT, 0);
glBindTexture(GL_TEXTURE_2D, g_FBOManager.m_fboDepthTex[idx]);
pglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,GL_TEXTURE_2D, g_FBOManager.m_fboDepthTex[idx], 0);
glBindTexture(GL_TEXTURE_2D, g_FBOManager.m_fboTex[idx]);
// attach a texture to FBO color attachment point
pglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, g_FBOManager.m_fboTex[idx], 0);
// check FBO status
pglBindFramebufferEXT( GL_FRAMEBUFFER_EXT, g_FBOManager.FboId(i) );
if(!CheckFramebufferStatus())
{
return false;
}
}
BindFrameBuffer(-1); // unbind fbo
if (GLGETERROR("1", fileBuf, lineBuf)) ; // check for glErrors
return true; // all ok
}
// code to init second set of textures before the render loop
const int w = g_XMLSettings->WWidth(); //res: 768 square
const int h = g_XMLSettings->WHeight();
glGenTextures(bufCount, &ttex[0]);
for (int i=0; i<bufCount; ++i)
{
glBindTexture(GL_TEXTURE_2D, ttex[i]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
}
const int bufCount = 3;
void EnableTexture1()
{
glActiveTextureARB(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, g_BackTexture);
glUniform1iARB(g_pPassAShader->m_clr_idx, 0);
}
void RenderLoop()
{
GLenum buffers[] = { GL_COLOR_ATTACHMENT0_EXT, GL_COLOR_ATTACHMENT1_EXT, GL_COLOR_ATTACHMENT2_EXT };
glColor4f(0.0f, 0.0f, 0.0f, 0.0f);
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
glUseProgramObjectARB(g_pPassAShader->m_glContext);
EnableTexture1();
//... code omitted to set transform matrix and supply to shader
if (!BindFrameBuffer(0))
assert(0);
const GLuint DTex = g_FBOManager.GetDepthTexture(0);
glBindTexture(GL_TEXTURE_2D, DTex);
pglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,GL_TEXTURE_2D, DTex, 0);
for (UINT i=0; i<bufCount; ++i)
{
glBindTexture(GL_TEXTURE_2D, g_FBOManager.GetTexture(i));
pglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT + i, GL_TEXTURE_2D, g_FBOManager.GetTexture(i), 0);
if (!CheckFramebufferStatus())
assert(0);
}
glDrawBuffers(bufCount,buffers);
// this is very important! if we don't clear it won't get written to
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glDisable(GL_BLEND);
EnableTexture1();
RenderVertexCache(0);
//... code omitted to set transform matrix and supply to shader
// render the second quad to other FBO tex
RenderVertexCache(0);
DisableShader(0);
BindFrameBuffer(-1); // unbinds fbo
//pass 2
if (!BindFrameBuffer(0))
assert(0);
// bind other set of textures to the fbo
for (UINT i=0; i<bufCount; ++i)
{
glBindTexture(GL_TEXTURE_2D,ttex[i]);
pglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT + i, GL_TEXTURE_2D, ttex[i], 0);
if (!CheckFramebufferStatus())
assert(0);
}
glDrawBuffers(bufCount,buffers);
// this is very important! if we don't clear it won't get written to
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
// bind our set from prev pass to the samplers as input
glUseProgramObjectARB(g_pPassBShader->m_glContext);
for (UINT i=0; i<bufCount; ++i)
{
glActiveTextureARB(GL_TEXTURE0+i);
glBindTexture(GL_TEXTURE_2D,g_FBOManager.GetTexture(i));
glUniform1iARB(g_pPassBShader->m_intex_idx[i], i);
}
VertexBufferManager2::RenderUsingOrthoEx(g_pPassBShader); // renders a full screen quad
DisableShader(0);
BindFrameBuffer(-1);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// pass 3
glUseProgramObjectARB(g_pPassCShader->m_glContext);
for (UINT i=0; i<bufCount; ++i)
{
glActiveTextureARB(GL_TEXTURE0+i);
glBindTexture(GL_TEXTURE_2D, ttex[i]);
glUniform1iARB(g_pPassCShader->m_intex_idx[i], i);
}
VertexBufferManager2::RenderUsingOrthoEx(g_pPassCShader);
if (GLGETERROR("at1", fileBuf, lineBuf)) ; // reports any glErrors
}
// the three shaders (fragment shaders only)
// vertex shaders transfer uv's and transform vertices (version set to 410 in all)
// shader for pass1
//--------------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------------
#version 410
uniform sampler2D g_ClrMap;
in vec2 g_InterpUV; // supplied by vshader
out vec4 g_FBOLayers[ 3 ];
void main(void)
{
vec4 tex = texture(g_ClrMap, g_InterpUV); // if we set fbo from texture only first texture renders
g_FBOLayers[0] = vec4(1,0,0,.5);
g_FBOLayers[1] = vec4(0,1,0,1);
g_FBOLayers[2] = vec4(1,1,0,1);
}
// shader pass 2
//--------------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------------
#version 410
uniform sampler2D g_inLayers0;
uniform sampler2D g_inLayers1;
uniform sampler2D g_inLayers2;
in vec2 g_InterpUV ;
out vec4 g_FBOLayers[ 3 ];
vec2 fTextureSize;
vec4 SamplePix(in int buf, in vec2 tCoords, in float lod)
{
if (buf==1)
return textureLod(g_inLayers1, tCoords, lod);
else if (buf==2)
return textureLod(g_inLayers2, tCoords, lod);
return textureLod(g_inLayers0, tCoords, lod);
}
void main(void)
{
ivec2 iCoords = ivec2(int(gl_FragCoord.x),int(gl_FragCoord.y));
ivec2 iTextureSize = textureSize(g_inLayers0,0);
fTextureSize = vec2(float(iTextureSize.x), float(iTextureSize.y));
vec2 coords = vec2(gl_FragCoord.x/iTextureSize.x,gl_FragCoord.y/iTextureSize.y);
for(int i=0; i<3; ++i)
{
g_FBOLayers[i] = vec4(0.,0.,0.,0.);
}
int j = 0;
for(; j < 2; ++j)
{
g_FBOLayers[j] = SamplePix(j,coords,0);
}
}
// shader pass 3
//--------------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------------
#version 410
uniform sampler2D g_inLayers0;
uniform sampler2D g_inLayers1;
uniform sampler2D g_inLayers2;
in vec2 g_InterpUV ;
out vec4 g_PixColour;
vec4 tFetch(in int buf, in ivec2 tCoords, in int lod)
{
if (buf==1)
return texelFetch(g_inLayers1, tCoords, lod);
if (buf==2)
return texelFetch(g_inLayers2, tCoords, lod);
return texelFetch(g_inLayers0, tCoords, lod);
}
void main(void)
{
ivec2 iCoords = ivec2(int(gl_FragCoord.x),int(gl_FragCoord.y));
ivec2 iTextureSize = textureSize(g_inLayers0,0);
vec2 coords = vec2(gl_FragCoord.x/iTextureSize.x,gl_FragCoord.y/iTextureSize.y);
vec4 colour = vec4(0.,0.,0.,0.);
int i = 0;
for(; i <2; ++i) // 3rd texture omitted for now
{
vec4 texel = tFetch(i,iCoords,0);
if(texel.a + colour.a <= 1.0)
{
colour.rgb += (texel.rgb*texel.a);
colour.a += texel.a;
}
else
{
texel.a -= (texel.a + colour.a) - 1.0;
colour.rgb += (texel.rgb*texel.a);
colour.a += texel.a;
break;
}
}
g_PixColour = colour;
}
Related
This question already has answers here:
In a fragment shader, why can't I use a flat input integer to index a uniform array of sampler2D?
(1 answer)
Why are glsl variables not working as expected?
(2 answers)
Why are Uniform variables not working in GLSL?
(1 answer)
Closed 2 years ago.
So I've managed to successfully implement batching into my engine, but have come across some weird behavior with the array of samplerCubes in my fragment shader. The batch renderer works fine with 2 texture units - I can successfully draw cubes with the right textures if I only bind 2 textures, but as soon as I add a 3rd to the mTextures vector, and use glUniform1i for that index in the samplerCube array, the wrong texture is displayed, even though the texture id (TexID) is correct (I checked this in the fragment shader).
The issue appears to be with my understanding of OpenGL as for some reason, the texture what should be displayed by textureCubes[2] (fragment shader uniform) is displayed by textureCubes[1], and textureCubes[2] displays the same texture as textureCubes[0]. What should be displayed by textureCubes[1] just doesn't exist with the 3rd texture bound.
Here's my code:
Main.cpp
#include "Window.h"
#include "Block.h"
#include "BatchRenderer.h"
#include "Shader.h"
#include "Camera.h"
void Submit(gfx::BatchRenderer* renderer, float height) //temporary to test batching
{
for (int i = 0; i < 16; i++)
{
for (int j = 0; j < 16; j++)
{
gfx::Block* block = new gfx::Block(j % 2 == 0 ? (i % 2 == 0 ? gfx::BlockType::DIRT : gfx::BlockType::GRASS) : gfx::BlockType::COBBLE, math::Vec3f(i * 5.0, height, j * 5.0));
renderer->Submit(block);
}
}
}
int main()
{
gfx::Window* window = new gfx::Window("MineClone", 800, 800);
gfx::Shader* shader = new gfx::Shader();
shader->FromFile(GL_VERTEX_SHADER, "Resources/ModelTest.vert");
shader->FromFile(GL_FRAGMENT_SHADER, "Resources/ModelTest.frag");
shader->RefreshProgram();
math::Mat4f projection = math::Mat4f::Perspective(70.0, window->GetWidth() / window->GetHeight(), 0.1, 1000.0);
gfx::Camera* camera = new gfx::Camera(projection, 0.05, 0.0015);
gfx::BatchRenderer* renderer = new gfx::BatchRenderer();
gfx::TextureCube* grass = new gfx::TextureCube("Resources/top.png", "Resources/dirt.png", "Resources/sides.png");
renderer->Submit(grass);
gfx::TextureCube* dirt = new gfx::TextureCube("Resources/dirt.png");
renderer->Submit(dirt);
gfx::TextureCube* cobble = new gfx::TextureCube("Resources/cobble.png");
renderer->Submit(cobble);
Submit(renderer, 0.0);
Submit(renderer, 5.0);
Submit(renderer, 10.0);
Submit(renderer, 15.0);
Submit(renderer, 20.0);
Submit(renderer, 25.0);
Submit(renderer, 30.0);
Submit(renderer, 35.0);
while (!window->IsClosed())
{
window->Update();
if (window->GetInputHandler()->IsKeyDown(VK_ESCAPE))
window->SwitchMouseState();
if (window->IsSynced())
camera->Update(window->GetInputHandler());
shader->Bind();
math::Mat4f projection = camera->GetProjection();
shader->SetUniform("projection", projection);
math::Mat4f view = camera->GetView();
shader->SetUniform("view", view);
shader->SetUniform("cubeTextures[0]", 0);
shader->SetUniform("cubeTextures[1]", 1);
shader->SetUniform("cubeTextures[2]", 2);
renderer->Render();
shader->Unbind();
}
return 0;
}
BatchRenderer.cpp
#include "BatchRenderer.h"
namespace gfx
{
BatchRenderer::BatchRenderer()
: mMesh(NULL)
{
}
BatchRenderer::~BatchRenderer()
{
mBlocks.clear();
mTextures.clear();
delete mMesh;
}
void BatchRenderer::Submit(Block* block)
{
MeshData data = block->GetMesh();
mMeshData.vertices.insert(mMeshData.vertices.end(),
data.vertices.begin(),
data.vertices.end());
for (int i = 0; i < 36; i++)
{
data.indices[i] += mBlocks.size() * 8;
}
mMeshData.indices.insert(mMeshData.indices.end(),
data.indices.begin(),
data.indices.end());
mMesh = Mesh::Make(mMeshData);
mBlocks.push_back(block);
}
void BatchRenderer::Submit(TextureCube* texture)
{
mTextures.push_back(texture);
}
void BatchRenderer::Render()
{
for (int i = 0; i < mTextures.size(); i++)
{
mTextures[i]->Bind(i);
}
mMesh->Render();
for (int i = 0; i < mTextures.size(); i++)
{
mTextures[i]->Unbind(i);
}
}
}
TextureCube.cpp
#include "TextureCube.h"
namespace gfx
{
TextureCube::TextureCube(std::string paths[6])
: Texture(TextureEnum::TEXTURE_CUBE)
{
glGenTextures(1, &mHandle);
glBindTexture(GL_TEXTURE_CUBE_MAP, mHandle);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
for (int i = 0; i < 6; i++)
{
std::vector<byte> pixels;
lodepng::decode(pixels, mWidth, mHeight, paths[i].c_str());
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGBA8, mWidth, mHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels.data());
}
glGenerateMipmap(GL_TEXTURE_CUBE_MAP);
glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
}
TextureCube::TextureCube(std::string path)
: Texture(TextureEnum::TEXTURE_CUBE)
{
glGenTextures(1, &mHandle);
glBindTexture(GL_TEXTURE_CUBE_MAP, mHandle);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
std::vector<byte> pixels;
lodepng::decode(pixels, mWidth, mHeight, path.c_str());
for (int i = 0; i < 6; i++)
{
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGBA8, mWidth, mHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels.data());
}
glGenerateMipmap(GL_TEXTURE_CUBE_MAP);
glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
}
TextureCube::TextureCube(std::string top, std::string bottom, std::string sides)
: Texture(TextureEnum::TEXTURE_CUBE)
{
glGenTextures(1, &mHandle);
glBindTexture(GL_TEXTURE_CUBE_MAP, mHandle);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
std::vector<byte> topPixels;
lodepng::decode(topPixels, mWidth, mHeight, top.c_str());
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGBA8, mWidth, mHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, topPixels.data());
std::vector<byte> bottomPixels;
lodepng::decode(bottomPixels, mWidth, mHeight, bottom.c_str());
glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GL_RGBA8, mWidth, mHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, bottomPixels.data());
std::vector<byte> sidesPixels;
lodepng::decode(sidesPixels, mWidth, mHeight, sides.c_str());
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGBA8, mWidth, mHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, sidesPixels.data());
glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GL_RGBA8, mWidth, mHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, sidesPixels.data());
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GL_RGBA8, mWidth, mHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, sidesPixels.data());
glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGBA8, mWidth, mHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, sidesPixels.data());
glGenerateMipmap(GL_TEXTURE_CUBE_MAP);
glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
}
TextureCube::~TextureCube()
{
glDeleteTextures(1, &mHandle);
mHandle = NULL;
}
void TextureCube::Bind(uint32_t slot)
{
glBindTextureUnit(slot, mHandle);
}
void TextureCube::Unbind(uint32_t slot)
{
glBindTextureUnit(slot, 0);
}
}
ModelTest.vert
#version 450 core
layout (location = 0) in vec3 position;
layout (location = 1) in vec3 normal;
layout (location = 2) in vec3 offset;
layout (location = 3) in float textureID;
uniform mat4 projection;
uniform mat4 view;
out vec3 TexPos;
out flat float TexID;
void main()
{
gl_Position = projection * view * vec4(position, 1.0);
TexPos = position - offset;
TexID = textureID;
}
ModelTest.frag
#version 450 core
out vec4 FragColour;
in vec3 TexPos;
in flat float TexID;
uniform samplerCube cubeTextures[3];
void main()
{
vec3 norm = normalize(TexPos);
int id = int(TexID);
FragColour = texture(cubeTextures[id], norm);
}
For anyone looking for a solution, it took me a while but I found it (I'm relatively new to OpenGL). The issue was I was setting the texture sampler slots individually using glUniform1i. To fix this, as cubeTextures is an array of samplerCubes, I created a struct for sampler data containing an int array and a length, and set the texture sampler slots using glUniform1iv.
I'm trying to implement a skybox and then use the cube map for the skybox to make a reflective sphere in my scene using some code I found editing to fit my project. The skybox shows but the image is almost corrupted looking, there is a basic outline of the mountains but no colour as you can see in the image.
http://i.imgur.com/kJT4aCV.jpg
I've been trying to make sure active texture and my shaders are correct but I just can't figure it out.
Vertex and fragment shader
#version 330 core
layout (location = 0) in vec3 position;
out vec3 TexCoords;
uniform mat4 projection;
uniform mat4 view;
void main()
{
vec4 pos = projection * view * vec4(position, 1.0);
gl_Position = pos.xyww;
TexCoords = position;
}
#version 330 core
in vec3 TexCoords;
out vec4 color;
uniform samplerCube skybox;
void main()
{
color = texture(skybox, TexCoords);
}
Load cubemap
GLuint loadCubemap(std::vector<const GLchar*> faces)
{
GLuint textureID;
glGenTextures(1, &textureID);
int width, height, numComponents;
unsigned char* image;
glBindTexture(GL_TEXTURE_CUBE_MAP, textureID);
for (GLuint i = 0; i < faces.size(); i++)
{
image = stbi_load(faces[i], &width, &height, &numComponents, 4);
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, image);
stbi_image_free(image);
}
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
return textureID;
}
Drawing skybox
glDepthFunc(GL_LEQUAL);
skyShader.Bind();
skyShader.Update(transform, camera);
view = glm::mat4(glm::mat3(camera.GetViewProjection()));
glUniformMatrix4fv(glGetUniformLocation(skyShader.getProg(), "view"), 1, GL_FALSE, glm::value_ptr(view));
glUniformMatrix4fv(glGetUniformLocation(skyShader.getProg(), "projection"), 1, GL_FALSE, glm::value_ptr(projection));
glBindVertexArray(skyboxVAO);
glActiveTexture(GL_TEXTURE0);
glUniform1i(glGetUniformLocation(skyShader.getProg(), "skybox"), 0);
glBindTexture(GL_TEXTURE_CUBE_MAP, skyboxTexture);
glDrawArrays(GL_TRIANGLES, 0, 36);
glBindVertexArray(0);
glDepthFunc(GL_LESS);
Let me know if any other parts would be useful to see
The texture was read in, and fed to OpenGL with inconsistent number of components per pixel
image = stbi_load(faces[i], &width, &height, &numComponents, 4); read in the image with 4 components
But when you fed it to OpenGL, glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, image); you fed it as a texture with 3 components per pixel, causing every 4 bytes to be interpreted as red when it should've been something else
I am trying to apply 1D texture to lines. It works but lines shimmer. I don't want this shimmering effect. Like on the picture.
I've also added a video about shimmering problem:
Shimmering Problem Video
How can I solve this problem? I am adding the codes below.
Vertex Shader:
attribute vec4 vertexMC;
uniform mat4 MCVCMatrix;
uniform mat4 VCDCMatrix;
attribute float tcoordMC;
varying float tcoordVC;
void main()
{
tcoordVC=(vertexMC.x+vertexMC.y+vertexMC.z)/3.0;
gl_Position=VCDCMatrix*MCVCMatrix*vertexMC;
}
Fragment Shader:
varying float tcoordVC;
uniform sampler1D texture1;
uniform vec3 GridColor;
void main()
{
gl_FragColor=vec4(GridColor, texture1D(texture1,tcoordVC).a);
if (gl_FragColor.a <= 0.0) discard;
}
Texture:
glGenTextures(1, &texture);
glActiveTexture(GL_TEXTURE1);
glBindTexture( GL_TEXTURE_1D, texture );
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_REPEAT );
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
unsigned char buf[ 16 * 4 ];
for( size_t i=0; i < sizeof( buf ); i+=4 )
{
buf[ i+0 ]=255;
buf[ i+1 ]=0;
buf[ i+2 ]=0;
}
buf[3]= 255;
buf[7]= 0;
buf[11]=255;
buf[15]=0;
buf[19]=255;
buf[23]=0;
buf[27]=255;
buf[31]=0;
buf[35]=255;
buf[39]=0;
buf[43]=255;
buf[47]=0;
buf[51]=255;
buf[55]=0;
buf[59]=255;
buf[63]=0;
glTexImage1D( GL_TEXTURE_1D, 0, 4, sizeof( buf ) / 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, buf );
InternalShader->Program.SetUniformi("texture1",1);
Draw Section:
glEnable( GL_TEXTURE_1D );
glBindTexture( GL_TEXTURE_1D, texture);
for(unsigned int i=0;i<GridsInternal.size();i++)
{
AGrid=GridsInternal[i];
if(!AGrid->GetActivity())
continue;
ACellBO=CellBOs[i];
AVBO=VBOs[i];
ALayout=Layouts[i];
AVBO->Bind();
SetMapperShaderParameters(i);
SetPropertyShaderParameters(i);
ACellBO->ibo.Bind();
glDrawRangeElements(GL_LINES, 0,
static_cast<GLuint>(ALayout->VertexCount-1),
static_cast<GLsizei>(ACellBO->indexCount),
GL_UNSIGNED_INT,
reinterpret_cast<const GLvoid *>(NULL));
AVBO->Release();
ACellBO->ibo.Release();
ACellBO->vao.Release();
}
glDeleteTextures(1, &texture);
glDisable(GL_TEXTURE_1D);
I am trying to splat vertex information into a 3D Texture.
Corresponding C++ code:
GLuint color_tex;
GLuint fb;
glGenTextures(1, &color_tex);
glBindTexture(GL_TEXTURE_3D, color_tex);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_REPEAT);
glTexImage3D(GL_TEXTURE_3D, 0, GL_R32UI, 32, 32, 32, 0, GL_RED_INTEGER, GL_UNSIGNED_INT, NULL);
//-------------------------
glGenFramebuffers(1, &fb);
glBindFramebuffer(GL_FRAMEBUFFER, fb);
//Attach one of the faces of the Cubemap texture to this FBO
glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, color_tex, 0);
//-------------------------
//Does the GPU support current FBO configuration?
GLenum status;
status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
switch(status)
{
case GL_FRAMEBUFFER_COMPLETE:
std::cout << "good" << std::endl;
default:
break;
}
//-------------------------
glClearColor(0,0,0,0);
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(splat_vertex_ids);
glBindVertexArray( mVAO );
glDrawArrays(mPrimitiveType, 0, mDrawSize);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
GLuint content[32*32*32];
glBindTexture(GL_TEXTURE_3D, color_tex);
glGetTexImage(GL_TEXTURE_3D, 0, GL_RED_INTEGER, GL_UNSIGNED_INT, &content);
for(int i = 0; i< 32*32*32; ++i)
if(content[i] != 0)
std::cout << content[i] << std::endl;
I read back the content to check if anything was rendered, but the texture only contains 0's.
My first thought was, that my shaders don't work correctly, so I replaced them by this :
Geometry Shader:
#version 330
layout(points) in;
layout(points, max_vertices = 1) out;
in vec3[] vPosition;
out vec2 oTexCoord;
void main(void)
{
oTexCoord = vec2(0.2);
gl_Position = vec4(0.2,0.2, 0.2,1);
gl_Layer = 0;
EmitVertex();
EndPrimitive();
}
Vertex Shader:
#version 330
layout(location = 0)in vec3 aPosition;
uniform vec3 uChunkStart;
uniform float uRes;
out vec3 vPosition;
void main(void)
{
vPosition = aPosition;
}
Fragment Shader:
#version 330
in vec2 oTexCoord;
out uint color;
void main(void)
{
color = 1337u;
}
Don't know whats wrong with this. Shouldn't it create a single dot? My first time doing such a thing.
EDIT: Rendering to a 2D texture also fails
I'm using integer texture and bind it to framebuffer to get render data.
I'v bind it to quad to display it on the screen and I'm sure the content of the texture is right.
But when I use glGetTexImage to get the content of the texture, I get random numbers.
here is the code to create the framebuffer:
glEnable(GL_TEXTURE_2D);
glGenFramebuffers(1, ¶m.fbo);
glGenTextures(1,¶m.triTex);
glBindTexture(GL_TEXTURE_2D, param.triTex);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_FALSE);
glTexImage2D(GL_TEXTURE_2D, 0, GL_R32UI, param.fboSize, param.fboSize, 0, GL_RED_INTEGER, GL_UNSIGNED_INT, 0);
glBindFramebuffer(GL_FRAMEBUFFER, param.fbo);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, param.triTex, 0);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glBindTexture(GL_TEXTURE_2D, 0);
The texture and framebuffer renders without problem.
here is the code of getting the content:
glBindTexture(GL_TEXTURE_2D, param.triTex);
glPixelStorei(GL_PACK_ALIGNMENT, 1);
triTexData = (unsigned int *)malloc(param.fboSize * param.fboSize * sizeof(unsigned int));
memset(triTexData, 0, sizeof(unsigned int) * param.fboSize * param.fboSize);
glGetTexImage(GL_TEXTURE_2D, 0, GL_RED_INTEGER, GL_UNSIGNED_INT, triTexData);
glBindTexture(GL_TEXTURE_2D,0);
Fragment shader and geometry shader
#version 330
flat in int color;
out vec4 fragColor;
void main(void)
{
fragColor = vec4(color,0.0,0.0,0.0);
}
#version 330
layout (triangles) in;
layout (triangle_strip, max_vertices = 3) out;
flat out int color;
void main(void)
{
gl_Position = gl_in[0].gl_Position;
color = gl_PrimitiveIDIn;
EmitVertex();
gl_Position = gl_in[1].gl_Position;
color = gl_PrimitiveIDIn;
EmitVertex();
gl_Position = gl_in[2].gl_Position;
color = gl_PrimitiveIDIn;
EmitVertex();
EndPrimitive();
};
Your fragment shader should actually be written this way to output to a GL_R32UI image:
#version 330
flat in int color;
out uint fragColor;
void main (void) {
fragColor = color;
}
At present, you are not reading back "random" numbers, you are just seeing what happens when you interpret floating-point data as integers without the proper conversion. Not pleasant, is it?