【问题标题】:openGL fragment shader and the original texel dataopenGL 片段着色器和原始纹素数据
【发布时间】:2014-10-05 07:00:27
【问题描述】:

所以我最近一直在学习一些 openGL。我最初一直在使用 SDL 库在屏幕上打印图像,但我认为尝试使用 openGL 实现类似的东西会很感兴趣,因此也能够将着色器应用于我的图像以获得整洁的效果,例如照明效果和夜晚/日周期等。我现在正在做的只是加载一个纹理,然后将该纹理应用到一个具有相同纹理大小的四边形。这很好用。

现在我想应用一些着色器。这是一个顶点和片段着色器的示例,我可以将其应用于我的纹理四边形之一:

in vec2 LVertexPos2D; 
void main()
 { 
      gl_Position = vec4( LVertexPos2D.x, LVertexPos2D.y, 0, 1); 
 }

什么都不做,然后是我的片段着色器:

out vec4 LFragment;
void main()
{
LFragment = vec4(1.0, 1.0, 1.0, 1.0);
}

这显然只是将我应用它的纹理变成了一个白色块,这并不是我想要的。不知何故,我需要检索当前的纹素数据,这样我就可以修改它而不是简单地改变它。

我读到对 texture2D 的函数调用应该返回当前像素数据的 vec4,但我还没有让它工作。 (很难找到对函数输入及其工作原理的良好解释)。此外,texture2D 据说已被弃用,但我也无法让它的替代品 (texture()) 工作。任何朝着正确方向的轻推将不胜感激!

编辑:我将提供更多关于我如何做事的信息,这是加载我的纹理的函数:

texture makeTexture(std::string fileLocation)
{
    texture tempTexture;
    SDL_Surface *mySurface = IMG_Load(fileLocation.c_str());
    if (mySurface == NULL)
    {
        std::cout << "Error in loading image at: " << fileLocation << std::endl;
        return tempTexture;
    }

    GLuint myTexture;
    glGenTextures(1, &myTexture);
    glBindTexture(GL_TEXTURE_2D, myTexture);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, mySurface->w, mySurface->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, mySurface->pixels);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glBindTexture(GL_TEXTURE_2D, 0);
    SDL_FreeSurface(mySurface);
    tempTexture.texture_id = myTexture;
    tempTexture.h = mySurface->h;
    tempTexture.w = mySurface->w;
    return tempTexture;
}

这是我的纹理结构:

struct texture
{
    int w;
    int h;
    GLuint texture_id;
};

这个函数将任何纹理绘制到给定的 x 和 y 坐标:

void draw(int y, int x, texture &tempTexture)
{
    glBindTexture(GL_TEXTURE_2D, tempTexture.texture_id);
    glBegin(GL_QUADS);
    glTexCoord2f(0, 1);
    glVertex2f(-1 + ((float)(x) / SCREEN_WIDTH) * 2, 1 - ((float)(y + tempTexture.h) / SCREEN_HEIGHT) * 2); //Bottom left
    glTexCoord2f(1, 1);
    glVertex2f(-1 + ((float)(x + tempTexture.w)/SCREEN_WIDTH)*2, 1 - ((float)(y + tempTexture.h) / SCREEN_HEIGHT) * 2); //Bottom right?
    glTexCoord2f(1, 0);
    glVertex2f(-1 + ((float)(x + tempTexture.w) / SCREEN_WIDTH) * 2, 1.0 - ((float)y / SCREEN_HEIGHT) * 2); //top right
    glTexCoord2f(0, 0);
    glVertex2f(-1 + ((float)(x) / SCREEN_WIDTH) * 2, 1.0 - ((float)y / SCREEN_HEIGHT) * 2); //Top left (notification: Coordinates are (x,y), not (y,x).
    glEnd();
    glBindTexture(GL_TEXTURE_2D, 0);
}

然后在我现在正在做的主渲染函数中:

draw(0, 0, myTexture);
glUseProgram(gProgramID);
glUniform1i(baseImageLoc, myTexture2.texture_id);
draw(100, 100, myTexture2);
glUseProgram(NULL);

myTexture 只是一片草地,而 myTexture2 是一个玩家角色,我想对其应用一些着色技巧。 gPriogramID 是一个加载了我上面提到的两个着色器的程序。

【问题讨论】:

标签: c++ opengl glsl shader


【解决方案1】:

为了在着色器中访问纹理数据,您必须执行以下操作:

  • 首先,您需要将glBind 纹理转换为特定纹理单元(使用glActiveTexture 更改活动纹理单元。
  • 将纹理单元索引作为统一采样器传递给着色器。
  • 在着色器中访问纹理,如下所示。

    // tex 保存要使用的纹理单元的值(不是纹理) 统一的sampler2D tex;

    空主() { vec4 颜色 = 纹理(tex,texCoord); LFragment = 颜色; }

您还需要将 texCoords 作为 in 顶点属性传递给着色器。

【讨论】:

  • 好的,谢谢。当你说通过纹理单元时,你的意思是纹理 ID?我正在尝试您所说的,但现在我的纹理只是一个黑色方块,所以我想我仍然在做一些非常错误的事情。我什至没有在当前设置中使用 glActiveTexture。
  • 啊,好吧不,我现在调用 glActiveTexture(GL_TEXTURE0),然后执行 glBindTexture(GL_TEXTURE_2D, myTexture2.texture_ID),然后执行 glUseProgram(gProgramID),然后尝试使用以下命令传递纹理单元:GLint baseImageLoc = glGetUniformLocation(gProgramID, "tex) 和 glUniform1i(baseImageLoc, GL_TEXTURE0); 但它仍然将我的纹理显示为黑色方块。
  • Nvm 让它工作了,谢谢!你把我推向了正确的方向。
  • @user3932479:这可能是你想出来的,但以防万一。在这种情况下,您为纹理单元传递给glUniform1i() 的值将是0,而不是GL_TEXTURE0。它只是纹理单元的索引,而不是枚举值。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-09-17
  • 1970-01-01
  • 2011-02-07
  • 2016-07-28
  • 1970-01-01
相关资源
最近更新 更多