繁体   English   中英

OpenGL glUniform1f不更新顶点着色器

[英]OpenGL glUniform1f not updating vertex shader

所有教程似乎都表明我在做正确的事情,顶点着色器正常工作,但是它无法通过使用glUniform1f函数识别主程序中的任何输入更改。 我在每行之后检查glGetError ,没有错误。 我检查了glGetShaderivglGetShaderInfoLog ,没有问题。 我正在测试SDL报告的OpenGL 2.1版(未知配置文件,但假设使用核心配置文件)。

#if defined(__WINDOWS__) || defined(_WIN32) || defined(_WIN64) || defined(__WIN32__) || defined(__TOS_WIN__)\
    || defined(__CYGWIN__)
    /* Compiling for Windows */
    #ifndef __WINDOWS__
        #define __WINDOWS__
    #endif
    #include <windows.h>
#endif/* Predefined Windows macros */

#include <SDL2/SDL.h>
#include <GL/GL.h>
#include <stdlib.h>
#include <stdio.h>
#include <error.h>

//return type not verified
void glGenBuffers();
void glBindBuffer();
void glBufferData();
unsigned int glCreateShader();
void glShaderSource();
void glCompileShader();
void glGetShaderiv();
void glGetShaderInfoLog();
unsigned int glCreateProgram();
void glAttachShader();
void glLinkProgram();
void glGetProgramiv();
void glGetProgramInfoLog();
void glVertexAttribPointer();
void glEnableVertexAttribArray();
void glUseProgram();
void glDeleteShader();
void glGenVertexArrays();
void glBindVertexArray();
GLint glGetUniformLocation();
void glUniform1f();
void glDeleteProgram();
void glDeleteBuffers();

int fixSDLconsole() {
    FILE *console = freopen("stdout.txt", "a",stdout);
    if (console == NULL) {return errno;}
    console = freopen("stdout.txt", "a",stderr);
    if (console == NULL) {return errno;}
    return 0;
}
void printGLVersionNumber() {
    int majorVersion;
    int minorVersion;
    int profile;
    SDL_GL_GetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, &majorVersion);
    SDL_GL_GetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, &minorVersion);
    SDL_GL_GetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, &profile);
    fprintf(stderr,"GL version %d.%d ",majorVersion,minorVersion);
    switch (profile) {
        case SDL_GL_CONTEXT_PROFILE_CORE: fprintf(stderr,"core (%d)\n",profile);break;
        case SDL_GL_CONTEXT_PROFILE_COMPATIBILITY: fprintf(stderr,"compatibility (%d)\n",profile);break;
        case SDL_GL_CONTEXT_PROFILE_ES: fprintf(stderr,"E.S. (%d)\n",profile);break;
        default: fprintf(stderr, "unknown profile: %d\n",profile);break;
    }
    return;
}
#define checkGlError(label) {int error = glGetError();if (error != GL_NO_ERROR) {error_at_line(0,0,__FILE__,__LINE__,"error=%d", error);goto label;}}
int main(int argc, char **argv) {
    SDL_Window *window = NULL;
    SDL_GLContext context = NULL;
    GLuint verticesGlIds[] = {0,0};
    GLuint vertexShaderGlId = 0;
    GLuint shaderProgramGlId = 0;
    if (fixSDLconsole()) {
        return errno;
    }
    if (SDL_Init(SDL_INIT_VIDEO) != 0) {
        error_at_line(1,0,__FILE__,__LINE__,"Unable to initialize SDL: %s",SDL_GetError());
        goto error;
    }
    printGLVersionNumber();

    window = SDL_CreateWindow("Window Title",SDL_WINDOWPOS_UNDEFINED,SDL_WINDOWPOS_UNDEFINED,640,640,SDL_WINDOW_OPENGL);
    if (window == NULL) {
        error_at_line(0,0,__FILE__,__LINE__,"Could not create window: %s", SDL_GetError());
        goto error;
    }
    context = SDL_GL_CreateContext(window);
    if (context == NULL) {
        error_at_line(0,0,__FILE__,__LINE__,"Could not create OpenGL context: %s", SDL_GetError());
        goto error;
    }

    glViewport(0,0,640,640);checkGlError(error);
    glClearColor(.9f,.9f,.9f,1.f);checkGlError(error);
    glEnableClientState(GL_VERTEX_ARRAY);checkGlError(error);
    glEnableClientState(GL_COLOR_ARRAY);checkGlError(error);

    float vertices[] = {
        -.5f,0.f,0.f,
        0.f,.5f,0.f,
        0.f,-.5f,0.f,
        0.f,.5f,0.f,
        .5f,.5f,0.f,
        0.f,0.f,0.f
    };
    float colors[] = {
        1.f,0.f,0.f,//red
        .5f,0.f,0.f,//red
        0.f,1.f,0.f,//green
        0.f,.5f,0.f,//green
        0.f,0.f,1.f,//blue
        0.f,0.f,.5f//blue
    };
    glGenBuffers(2, &verticesGlIds);checkGlError(error);

    glBindBuffer(GL_ARRAY_BUFFER, verticesGlIds[0]);checkGlError(error);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);checkGlError(error);

    glBindBuffer(GL_ARRAY_BUFFER, verticesGlIds[1]);checkGlError(error);
    glBufferData(GL_ARRAY_BUFFER,sizeof(colors),colors, GL_STATIC_DRAW);checkGlError(error);

    char *vertexShader =
        "#version 120\n"\
        "attribute vec3 aPos;\n"\
        "uniform float i;\n"\
        "void main() {\n"\
        "gl_FrontColor=gl_Color;\n"\
        "gl_Position = vec4(aPos.x+i/2,aPos.y,aPos.z,1.0);\n"\
        "}\n";
    vertexShaderGlId = glCreateShader(GL_VERTEX_SHADER);checkGlError(error);
    if (vertexShaderGlId == 0) {error_at_line(0,0,__FILE__,__LINE__,"vertex shader could not be created");goto error;}
    glShaderSource(vertexShaderGlId, 1, &vertexShader, NULL);checkGlError(error);
    glCompileShader(vertexShaderGlId);checkGlError(error);
    {
        GLint success;
        glGetShaderiv(vertexShaderGlId, GL_COMPILE_STATUS, &success);checkGlError(error);
        if (success == GL_FALSE) {
            char infoLog[512];
            glGetShaderInfoLog(vertexShaderGlId, 512, NULL, infoLog);checkGlError(error);
            error_at_line(0,0,__FILE__,__LINE__,"Vertex Shader problem: %s", infoLog);
            goto error;
        }
    }

    shaderProgramGlId = glCreateProgram();checkGlError(error);
    if (shaderProgramGlId == 0) {error_at_line(0,0,__FILE__,__LINE__,"shader program could not be created");goto error;}
    glAttachShader(shaderProgramGlId, vertexShaderGlId);checkGlError(error);
    glLinkProgram(shaderProgramGlId);checkGlError(error);
    {
        int success;
        glGetProgramiv(shaderProgramGlId, GL_LINK_STATUS, &success);checkGlError(error);
        if (!success) {
            char infoLog[512];
            glGetProgramInfoLog(shaderProgramGlId, 512, NULL, infoLog);checkGlError(error);
            error_at_line(0,0,__FILE__,__LINE__,"Shader program problem: %s", infoLog);
        }
    }

    glDeleteShader(vertexShaderGlId);checkGlError(error);

    GLint iLocation = glGetUniformLocation(shaderProgramGlId, "i");checkGlError(error);
    if (iLocation == -1) {error_at_line(0,0,__FILE__,__LINE__,"uniform i not found in shader");goto error;}
    error_at_line(0,0,__FILE__,__LINE__,"iLocation: %d", iLocation);

    for (int frame = 0; frame < 100; ++frame) {
        glClear(GL_COLOR_BUFFER_BIT);checkGlError(error);
        glUseProgram(shaderProgramGlId);checkGlError(error);

        glBindBuffer(GL_ARRAY_BUFFER, verticesGlIds[0]);    checkGlError(error);
        glVertexPointer(3,GL_FLOAT,0,0);    checkGlError(error);
        glBindBuffer(GL_ARRAY_BUFFER, verticesGlIds[1]);    checkGlError(error);
        glColorPointer(3,GL_FLOAT,0,0); checkGlError(error);
        glUniform1f(iLocation, (float) (frame%2));  checkGlError(error);
        glDrawArrays(GL_TRIANGLES, 0,sizeof(vertices)/sizeof(float)/3); checkGlError(error);
        glBindBuffer(GL_ARRAY_BUFFER, 0);   checkGlError(error);
        SDL_GL_SwapWindow(window);
        SDL_Delay(100);
    }
    glDeleteProgram(shaderProgramGlId);
    glDeleteShader(vertexShaderGlId);
    glDeleteBuffers(sizeof(verticesGlIds)/sizeof(GLuint), verticesGlIds);
    SDL_GL_DeleteContext(context);
    SDL_Delay(3000);
    SDL_DestroyWindow(window);
    SDL_Quit();
    return EXIT_SUCCESS;
    error:
    glDeleteProgram(shaderProgramGlId);
    glDeleteShader(vertexShaderGlId);
    glDeleteBuffers(sizeof(verticesGlIds)/sizeof(GLuint), verticesGlIds);
    if (context != NULL) SDL_GL_DeleteContext(context);
    if (window != NULL) SDL_DestroyWindow(window);
    SDL_Quit();
    return EXIT_FAILURE;
}
#if defined(__WINDOWS__)
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd) {
    char *argv[1] = {(char *) 0};
    return main(0, argv);
}
#endif

请注意,我对OpenGL的扩展功能加载问题和例程(例如SDL的SDL_GL_LoadLibrarySDL_GL_GetProcAddress不熟悉,我只是在文件顶部手动定义方法签名,然后通过链接器导入GL。 我不希望这是一个问题,但我知道,这是我尚未调查的唯一问题,这可能会导致我的问题。

gl_Position期望Clip-space坐标,该坐标是大小为[2w,2w,2w,w]的hiper-cube。
对于vec4(x, y, z, w)如果[x,y,z]中的任何一个不在[-w,w]范围内,则将修剪顶点。
GPU将在片段着色器之前将坐标自动转换为NDC空间 x/w, y/w, z/w, 1 (也称为“透视除法”)。

您的GLSL代码gl_Position = vec4(aPos.x+i/2,aPos.y,aPos.z,1.0); 使用制服i
您可以通过glUniform1f(iLocation, (float) (frame%2));更新它glUniform1f(iLocation, (float) (frame%2));

首先是frame%2 01被传递给GPU。 使用当前的顶点数据,只能绘制两对三角形。

第二个问题是frame的值为0 <= frame < 100 因此,如果您传递frame而不是frame%2 ,那么对于大多数值, aPos.x + i/2将落在Clip空间之外,并且您只会看到前两个三角形对或其中的一部分。

因此,您可以这样声明函数:

 void glUniform1f(); 

通过省略任何参数,编译器将假定所有参数均为int类型。 对于大多数其他GL函数,这是偶然的,因为无论如何,这些参数在大多数情况下都是整数类型,但是对于glUniform1f ,这将意味着该函数参数已转换为整数,但是隐式地重新解释了所得到的位模式作为函数的GLfloat ,因为glUniform1f的实际原型是这样的

void glUniform1f(int location, GLfloat value);

请注意,我对OpenGL的扩展功能加载问题和例程(例如SDL的SDL_GL_LoadLibrarySDL_GL_GetProcAddress不熟悉,我只是在文件顶部手动定义方法签名,然后通过链接器导入GL。

你不应该这样做。 您尝试访问的GL函数甚至可能根本不会被库导出 如果您不想手动处理每个函数指针的加载,则可以使用现有的OpenGL加载器之一

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM