当前位置: 首页 > 知识库问答 >
问题:

OepnGL采样MultiPE纹理返回相同的纹理颜色

云俊美
2023-03-14

主要的cpp

#define GLFW_INCLUDE_NONE
#include <GLFW/glfw3.h>
#include <glad/glad.h>
#include <fstream>
#include <iostream>
#include <string>
#include <stdio.h>
#include <SOIL/SOIL.h>

typedef struct vertex{
    float x; float y; float z;
    float texX; float texY;
    float texIndex;
} vertex;

void readTextFile(const char* path, std::string* dst);

int main(){
    std::cout << 3 << std::endl;
    
    GLFWwindow* window;
    
    if(!glfwInit())
        return -1;
    
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
    
    window = glfwCreateWindow(640, 480, "Geometry Shader Bathing with Texture Atlas", NULL, NULL);
    if(!window){    
        glfwTerminate();
        return -1;
    }
    
    glfwMakeContextCurrent(window);
    
    gladLoadGL();
    
    glfwSwapInterval(1);
    glFrontFace(GL_CW);
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    
    //create and set vertex buffer
    vertex vertices[] = {
        -1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f,
        -1.0f,  0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
         0.0f, -1.0f, 0.0f, 1.0f, 1.0f, 0.0f,
        
         0.0f, -1.0f, 0.0f, 1.0f, 1.0f, 0.0f,
        -1.0f,  0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
         0.0f,  0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
        
         0.0f,  0.0f, 0.0f, 0.0f, 1.0f, 1.0f,
         0.0f,  1.0f, 0.0f, 0.0f, 0.0f, 1.0f,
         1.0f,  0.0f, 0.0f, 1.0f, 1.0f, 1.0f,
        
         1.0f,  0.0f, 0.0f, 1.0f, 1.0f, 1.0f,
         0.0f,  1.0f, 0.0f, 0.0f, 0.0f, 1.0f,
         1.0f,  1.0f, 0.0f, 1.0f, 0.0f, 1.0f,
    };
    
    GLuint vertexBuffer;
    glGenBuffers(1, &vertexBuffer);
    glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_DYNAMIC_DRAW);
    
    //create vertex shader
    std::string* shaderSource = new std::string();
    
    readTextFile("shader/vertexShader.glsl", shaderSource);
    const char* vertexShaderSourcePtr = shaderSource->c_str();
    
    GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(vertexShader, 1, &vertexShaderSourcePtr, NULL);
    glCompileShader(vertexShader);

    GLint status;
    glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &status);
    if(status == GL_FALSE){
        char buffer[512];
        glGetShaderInfoLog(vertexShader, 512, NULL, buffer);
        std::cout << "vertexShader FAIL : " << std::endl <<
            shaderSource <<std::endl 
            << buffer << std::endl;
    }else{
        std::cout << "vertexShader compile success!" << std::endl;
    }
    
    //create fragment shader
    readTextFile("shader/fragmentShader.glsl", shaderSource);
    const char* fragmentShaderSourcePtr = shaderSource->c_str();
    
    GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(fragmentShader, 1, &fragmentShaderSourcePtr, NULL);
    glCompileShader(fragmentShader);
    
    glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &status);
    if(status == GL_FALSE){
        char buffer[512];
        glGetShaderInfoLog(fragmentShader, 512, NULL, buffer);
        std::cout << "fragmentShader FAIL : " << std::endl <<
            shaderSource <<std::endl 
            << buffer << std::endl;
    }else{
        std::cout << "fragmentShader compile success!" << std::endl;
    }
    
    delete shaderSource;
    
    //create and set program
    GLint program = glCreateProgram();
    glAttachShader(program, vertexShader);
    glAttachShader(program, fragmentShader);
    
    glBindAttribLocation(program, 0, "inPos");
    glBindAttribLocation(program, 1, "inTex");
    glBindAttribLocation(program, 2, "inTexIndex");
    
    glLinkProgram(program);
    //set frameBuffer(renderTarget) index and fragmentShader output name
    glBindFragDataLocation(program, 0, "outColor"); 
    glUseProgram(program);
    
    //create and set texture
    int width = 384;
    int height = 384;
    unsigned char* textureRawData0 = SOIL_load_image("resource/character/test0.png", &width, &height, 0, SOIL_LOAD_RGBA);
    unsigned char* textureRawData1 = SOIL_load_image("resource/character/test1.png", &width, &height, 0, SOIL_LOAD_RGBA);
    
    glUniform1i(glGetUniformLocation(program, "texture0"), 0);
    glUniform1i(glGetUniformLocation(program, "texture1"), 1);
    
    GLuint texture1;
    glGenTextures(1, &texture1);
    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, texture1);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, textureRawData0);
    SOIL_free_image_data(textureRawData0);
    
    std:: cout << "texture0: " << glGetUniformLocation(program, "texture0") << std::endl;
    
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    
    GLuint texture2;
    glGenTextures(1, &texture2);
    glActiveTexture(GL_TEXTURE0 + 1);
    glBindTexture(GL_TEXTURE_2D, texture2);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, textureRawData1);
    SOIL_free_image_data(textureRawData1);

    std:: cout << "texture1: " << glGetUniformLocation(program, "texture1")  << std::endl;
    
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    
    
    //input layout : vertex Attribute
    GLuint vao;
    glGenVertexArrays(1, &vao);
    glBindVertexArray(vao);
    
    
    glLinkProgram(program);
    
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(vertex), 0);
    glEnableVertexAttribArray(1);
    glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(vertex), (void*)(3 * sizeof(float)));
    glEnableVertexAttribArray(2);
    glVertexAttribPointer(2, 1, GL_FLOAT, GL_FALSE, sizeof(vertex), (void*)(5 * sizeof(float)));
    
    
    while(!glfwWindowShouldClose(window)){
        int width, height;
        glfwGetFramebufferSize(window, &width, &height);
        
        glViewport(0, 0, width, height);
        glClearColor(1.0f, 1.0f, 1.0f, 0.0f);
        glClear(GL_COLOR_BUFFER_BIT);
        
        glDrawArrays(GL_TRIANGLES, 0, 12);
        
        glfwSwapBuffers(window);
        glfwPollEvents();
    }
    
    glfwTerminate();
    return 0;
}

void readTextFile(const char* path, std::string* dst){
    std::ifstream f;
    f.open(path);
    
    if(f.is_open()){
        std::string buff;
        dst->clear();
        while(!f.eof()){
            std::getline(f, buff);
            dst->append(buff);
            dst->push_back('\n');
        }
        
        dst->push_back('\0');
        
        f.close();
    }else{
        std::cout << "파일 열기 실패 : " << *dst << std::endl;
    }
}

附言

#version 330 core

in vec2 outTex;
in float outTexIndex;
out vec4 outColor;

uniform sampler2D texture0;
uniform sampler2D texture1;

void main(){
    if(outTexIndex == 0.0f){
        outColor = texture(texture0, outTex);
    }

    else if(outTexIndex == 1.0f){
        outColor = texture(texture1, outTex) + vec4(0.5f, 0.5f, 0.5f, 1.0f);
    }
}

输入布局(顶点属性)工作正常。TexIndex已正确传输。1.0f和0.0f

但问题是

//片段着色器

纹理(texture 0, outTex);

纹理(texture 1, outTex);

两者都返回相同的纹理颜色,但它实际上与test1的纹理不同。png和test2。巴布亚新几内亚。我的代码有什么问题?

我试着跟随@rabbi76的答案

#version 330 core

in vec2 outTex;
in float outTexIndex;
out vec4 outColor;

uniform sampler2D texture0;
uniform sampler2D texture1;

void main()
{
    vec4 c1 = texture(texture0, outTex) + vec4(0.5f, 0.0f, 0.0f, 1.0f);
    vec4 c2 = texture(texture1, outTex) + vec4(0.0f, 0.5f, 0.0f, 1.0f);
    outColor = mix(c1, c2, outTexIndex); 
}

已应用颜色,但仍从同一纹理采样。看起来有点像glActiveTexture(i);没用。

ps.test1。png和test2。png是完全不同的图片。上面的截图是test1。巴布亚新几内亚

当我改变的时候

glGenTexture(1, &texture0);
glGenTexture(1, &texture1);

glGenTexture(0, &texture0);
glGenTexture(0, &texture1);

然后sampler2D texture 0和sampler2D texture 1都从texture 1test1.png采样(不形成test0.png的texture 0)

发生了什么事?

vs

#version 330

in vec3 inPos;
in vec2 inTex;
in float inTexIndex;

out vec2 outTex;
out float outTexIndex;

void main(){
    outTex = inTex;
    gl_position = vec4(inPos, 1.0f);
    outTexIndex = inTexIndex;
}

共有2个答案

宦烈
2023-03-14

我想,如果我有一个多纹理的编译示例,它工作起来没有问题,那么我就可以发现我的代码在代码行与示例进行比较时出现的问题。所以我找到了这个。

辅导的

示例代码

它是基于SDL的。所以我将初始化代码和循环更改为glfw。它在我的环境中运行良好。

即使我将代码的纹理加载部分与示例完全相同,问题仍然没有得到解决。所以一定是另一部分造成了这个问题。最后,我找到了这个。

//input layout : vertex Attribute
GLuint vao;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);

//*****here!*****
//glLinkProgram(program);    
    
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(vertex), 0);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(vertex), (void*)(3 * sizeof(float)));
glEnableVertexAttribArray(2);
glVertexAttribPointer(2, 1, GL_FLOAT, GL_FALSE, sizeof(vertex), (void*)(5 * sizeof(float)));

在我添加两个字符后 "//", 结果显示如我所想。我不确定一行代码出现问题的原因。

宋安晏
2023-03-14

由于条件if(outTexIndex==0.0f)依赖于片段着色器输入,这可能会导致未定义的行为。

参见(最新)OpenGL着色语言4.60规范-8.9。纹理函数

[...]某些纹理函数(非“Lod”和非“Grad”版本)可能需要隐式导数。隐式导数在非均匀控制流和非片段着色器纹理获取中未定义。[...]

分别为非均匀流量控制。

同时查找纹理和mix颜色以解决问题:

#version 330 core

in vec2 outTex;
in float outTexIndex;
out vec4 outColor;

uniform sampler2D texture0;
uniform sampler2D texture1;

void main()
{
    vec4 c1 = texture(texture0, outTex);
    vec4 c2 = texture(texture1, outTex) + vec4(0.5f, 0.5f, 0.5f, 1.0f);
    outColor = mix(c1, c2, outTexIndex); 
}
 类似资料:
  • 我对如何将纹理绑定到GLSL中的插槽有点困惑。以下是我的着色器: 当我设置矩阵时,我需要查询统一位置,然后手动设置该位置的值,执行如下操作: 然而,据我所知,我不需要这样做来初始化我的纹理采样器。在设置时,我似乎只需要这样做: 所以,我的问题是,为什么我不需要对纹理进行与矩阵相同的处理?OpenGL运行时如何“知道”我绑定的纹理应该是我定义的采样器?如果我想拥有多种纹理,我该怎么做呢?

  • 使用OpenGL(核心配置文件,4.4),将同一个采样器对象同时绑定到2个不同的纹理单元是否“合法”? 我的测试表明它是有效的,但我不知道我的司机是否原谅了我,或者这是一项功能。

  • 我创建了一个类来保存我的模型信息。我必须正确渲染模型并正确包装纹理,但是由于某种原因,如果我有多个模型,它会将我所有的模型纹理化为仅1个纹理,正如您在这张图片中看到的:http://imgur.com/d0glIwF 知道为什么会这样吗? 这是我的代码: 提前谢谢你。

  • 有人能给我解释一下,我如何在OpenGL中渲染多个不同纹理的物体吗? 我认为我接近最终结果,但目前我被困在这里,我不知道下一步需要做什么。真的需要一些帮助! 目前,这就是我所拥有的: > < li> drawSphere():根据经度和纬度的数量绘制UV球体 int numberOfVerices = 0; SetupGeometry():该方法用于绑定顶点和纹理坐标。 DrawSphere(30

  • 如何为一个纹理阵列创建多个采样器 到目前为止,我一直依赖OpenGL来确定声明的sampler是指我与绑定的纹理数组。 我尝试在片段着色器中指定两个采样器,但片段着色器出现编译错误: 我没想到这会起作用,但是,我不确定片段着色器编译器是否检查采样器是否分配了纹理,所以可能是其他问题。 我尝试生成和绑定采样器对象,但我仍然得到一个片段着色器错误: 我想坚持使用OpenGL的较低版本,有可能吗?非常感

  • 之前用过了静态的纹理设置材质,这次来尝试一下动态的变换,这次来尝试颜色变换 先创建工程,步骤略 添加一个管线,参考官方示例Polyline Volume,每个示例的代码,都用一下,说不定学到点新东西呢~ (#^.^#) 这里按理说应该是要给纹理赋值了,要它动态变化,一般有两种思路,其一是赋值一次,然后之后用代码(定时器)动态修改材质,其二是使用回调,在上一篇鹰眼图中尝试过,发现回调效果比较好,不会