在片元着色器(GLSL)中定义多个结构并将它们设置为统一变量:

huangapple go评论70阅读模式
英文:

Defining multiple structs and setting them as uniforms in Fragment Shader GLSL

问题

我试图创建一个材质结构和一个光线结构,我将在GLSL片段着色器中使用它们。当我只定义一个结构(无论是材质还是光线)时,我可以正确渲染我的场景,但当我同时定义它们时,调用glGetUniformLocation(...)会返回-1,对于材质结构(定义的顺序无关紧要),就好像它们不存在或未被使用。我需要使用这些结构以备将来使用,请不要要求我使用POD(Plain Old Data)结构。我想学习如何将多个结构作为uniform变量上传。谢谢。

以下是顶点着色器和片段着色器的代码,以及如何设置uniform变量:

顶点着色器:

#version 450

layout (location = 0) in vec3 pos;
layout (location = 1) in vec3 norm;

layout (location = 2) out vec3 v_space_norm;
layout (location = 3) out vec3 v_space_pos;

layout(location = 0) uniform mat4 to_screen_space; // mvp
layout(location = 1) uniform mat4 to_view_space; //mv
layout(location = 2) uniform mat3 normals_to_view_space;

void main() {
    gl_Position = to_screen_space * vec4(pos, 1.0);
    v_space_norm = normals_to_view_space * norm;
    v_space_pos = (to_view_space * vec4(pos, 1.0)).xyz;
}

片段着色器:

#version 450
precision mediump float;

//------------ Structs ------------

layout (location = 2) in vec3 v_space_norm;
layout (location = 3) in vec3 v_space_pos;

//------------ Uniforms ------------
layout(location = 1) uniform mat4 to_view_space; //mv
layout(location = 3) uniform struct{
    vec3 position;
    float intensity;
} light;

layout(location = 6) uniform struct{
    vec3 ka;
    vec3 kd;
    vec3 ks;
    float shininess;
} material;

out vec4 color;

void main() {
    vec3 v_space_norm = normalize(v_space_norm);
    vec3 l = normalize((to_view_space * vec4(light.position, 1)).xyz - v_space_pos);
    vec3 h = normalize(l + vec3(0, 0, 1));

    float cos_theta = dot(l, v_space_norm);
    if (cos_theta >= 0) {
        vec3 diffuse = material.kd * max(cos_theta, 0);
        vec3 ambient = material.ka;
        vec3 specular = material.ks * pow(max(dot(h, v_space_norm), 0), material.shininess);
        color = vec4(light.intensity * (specular + diffuse) + ambient, 1);
    } else {
        color = vec4(material.ka, 1);
    }
}

设置uniform变量的方式:

// ...
program->SetUniform("light.position", light.position);
program->SetUniform("light.intensity", light.intensity);
program->SetUniform("material.ka", material.ambient);
program->SetUniform("material.kd", material.diffuse);
program->SetUniform("material.ks", material.specular);
program->SetUniform("material.shininess", material.shininess);
// ...

你提到的SetUniform函数中,你使用了glGetUniformLocation来获取uniform变量的位置。如果你的uniform变量名称与GLSL代码中的命名完全匹配,那么这种方法应该正常工作。不过,如果出现问题,可以手动设置uniform变量的位置,通过在GLSL代码中使用layout(location = ...) uniform ...来指定uniform变量的位置。这样,你可以直接通过位置来设置结构体的成员。

总之,你的GLSL代码和uniform变量设置的方式看起来没有问题,但如果你遇到问题,可以检查uniform变量名称是否正确匹配或手动设置位置。

英文:

Im trying to create a material struct and a light struct that I will use in GLSL fragment shader. I can render the scene I have correctly when I have only one struct defined (either material or light) but when I define both of them together the glGetUniformLocation(...) calls return -1 for Material structs (order of defnitions does not matter) as if they are not there or not being used. I need to use the structs for the future use please do not ask me to use PODs. I want to learn how to upload multiple structs as uniforms. Thanks.

Here is the vertex shader:

#version 450

layout (location = 0) in vec3 pos;
layout (location = 1) in vec3 norm;

layout (location = 2) out vec3 v_space_norm;
layout (location = 3) out vec3 v_space_pos;

layout(location = 0) uniform mat4 to_screen_space; // mvp
layout(location = 1) uniform mat4 to_view_space; //mv
layout(location = 2) uniform mat3 normals_to_view_space;
//layout(location = 4) float light_intensity;

void main() {
gl_Position = to_screen_space \* vec4(pos, 1.0);
v_space_norm = normals_to_view_space \* norm;
v_space_pos = (to_view_space \* vec4(pos, 1.0)).xyz;
}

and fragment shader:

#version 450
precision mediump float;
//------------ Structs ------------
// struct Light{
//      vec3 position;
//      float intensity;
// };

//------------ Variying ------------
layout (location = 2) in vec3 v_space_norm;
layout (location = 3) in vec3 v_space_pos;

//------------ Uniforms ------------
layout(location = 1) uniform mat4 to_view_space; //mv
//layout(location = 3) uniform vec3 light_position;

//layout(location = 4) uniform float light_intensity;
layout(location = 3) uniform struct{
     vec3 position;
     float intensity;
}light;

layout(location = 6) uniform struct{
     vec3 ka;
     vec3 kd;
     vec3 ks;
     float shininess;
} material;


out vec4 color;

void main() {
     vec3 v_space_norm = normalize(v_space_norm);
     vec3 l =  normalize( (to_view_space * vec4(light.position, 1)).xyz - v_space_pos);//normalize(l); //light vector
     vec3 h = normalize(l + vec3(0,0,1)); //half vector

     float cos_theta = dot(l, v_space_norm);
     if(cos_theta >= 0)
     {
          vec3 diffuse = material.kd * max(cos_theta,0);
          vec3 ambient = material.ka;
          vec3 specular= material.ks * pow(max(dot(h, v_space_norm),0), material.shininess);
          color = vec4(light.intensity * (specular + diffuse) + ambient, 1);
     }
     else
     {
          color = vec4(material.ka,1);
     }
}

And the way I set uniforms:

...
program->SetUniform("light.position", light.position);
program->SetUniform("light.intensity", light.intensity);
program->SetUniform("material.ka", material.ambient);
program->SetUniform("material.kd", material.diffuse);
program->SetUniform("material.ks", material.specular);
program->SetUniform("material.shininess", material.shininess);
...

The definition of SetUniform:

GLint location = glGetUniformLocation(glID, name);
if (location == -1)
{
	std::cout << "ERROR::SHADER::UNIFORM::" << name << "::NOT_FOUND"<<std::endl;
	return;
}
glUniform1f(location, value);//or what ever the type is there are definitions for all types!!!

I was unable to find anything online about my problem

I was hoping to see the teapot rendered and blinn shaded. And I can get that if I only define one struct and then upload the other properties as PODs.

So using the fragment shader below:

//------------ Uniforms ------------
layout(location = 1) uniform mat4 to_view_space; //mv
layout(location = 3) uniform vec3 light_position;

layout(location = 4) uniform float light_intensity;
// layout(location = 3) uniform struct{
//      vec3 position;
//      float intensity;
// }light;
...

//using light_position and light_intensity instead of light.position, light.intensity

Of course setUniform calls are also changed accordingly.
enter image description here

But if I use both of the structs I get this:
enter image description here

Edit: Instead of accessing via glGetUniformLocation(glID, name); I can manually set each variable via layout location number. Now the question becomes "Can I set the structs using the string variable names?"

答案1

得分: 1

使用命名的结构体如下:

struct Light{
      vec3 position;
      float intensity;
};

然后,根据OpenGL维基的说法,将它们用作uniform变量似乎是正确的方法(我可能曾尝试过,但不记得了...)。

layout(location = 3) uniform Light light;

所以,下面这种写法:

layout(location = 3) uniform struct{
     vec3 position;
     float intensity;
}light;

要么不太好,要么属于我知识之外的未定义行为。

英文:

Using named structs like:

struct Light{
      vec3 position;
      float intensity;
};

And then using them as uniforms seems to be the correct way to go according to OpenGL wiki (I could have sworn I tried that but oh well...).

layout(location = 3) uniform Light light;

So,

layout(location = 3) uniform struct{
     vec3 position;
     float intensity;
}light;

this is either not good or undefined behavior which is beyond my knowledge.

答案2

得分: 0

我不知道你在代码中做错了什么,因为你没有提供一个能够复现你的问题的最小示例。所以我无法指出你做错了什么。

通过编写我的自己的应用程序来完成以下任务:

  1. 加载一个GLFW窗口
  2. 加载OpenGL上下文
  3. 根据你的GLSL脚本(顶点和片段)加载一个着色器
  4. 加载所有的uniform变量
  5. 打印所有的uniform变量

这是我的应用程序的输出:

SHADER: 加载uniform变量
(位置 = 0): light.intensity       <- 注意:这看起来有点奇怪,因为
(位置 = 1): light.position        我没有搜索正确的位置
(位置 = 2): material.ka           id来获取每个uniform变量的名称。我在猜测
(位置 = 3): material.kd           它们,就好像你从未手动设置过位置
(位置 = 4): material.ks           。打印操作发生在一个for循环中。如果你
(位置 = 5): material.shininess    从GLSL脚本中删除所有的`layout(location=*)`
(位置 = 6): normals_to_view_space ,这里打印出来的id将会正常。

SHADER: 打印uniform变量
Uniform 'light.intensity' 位置为 (4)
Uniform 'light.position' 位置为 (3)
Uniform 'material.ka' 位置为 (6)
Uniform 'material.kd' 位置为 (7)
Uniform 'material.ks' 位置为 (8)
Uniform 'material.shininess' 位置为 (9)
Uniform 'normals_to_view_space' 位置为 (2)
Uniform 'to_screen_space' 位置为 (0)
Uniform 'to_view_space' 位置为 (1)

所以,在我的测试应用程序中,uniform变量的位置被成功加载。

这是我使用的代码。请注意,我还使用了OpenGL版本4.50,使用核心配置。我的代码是从learnopengl教程提供的代码进行了适应。

main.cpp

#include "shader.hpp"

int main(int argc, char **argv) {
    GLFWwindow* window = NULL;
    Shader shader;
    GLuint vao;

    glewExperimental = true;
    if (!glfwInit()) {
        std::cout << "GLFW::FAILED" << std::endl;
        return false;
    } else {
        glfwWindowHint(GLFW_SAMPLES, 4);
        glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4); // 我们的OpenGL版本必须设置为
        glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 5); // 4.50(与着色器版本相同)
        glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
        glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

        window = glfwCreateWindow(800, 600, "GLSLloader.exe", NULL, NULL);

        if (window == NULL) {
            std::cout << "GLFW::FAILED::CREATE::WINDOW" << std::endl;
            return false;
        } else {
            glfwMakeContextCurrent(window);

            if (glewInit() != GLEW_OK) {
                std::cout << "GLEW::FAILED" << std::endl;
            } else {
                glGenVertexArrays(1, &vao);
                glBindVertexArray(vao);

                shader.LoadProgram();
                shader.PrintUniforms();
            }
        }
    }

    return 0;
}

shader.hpp

#ifndef _MY_SHADER_LOADER_
#define _MY_SHADER_LOADER_

// 你可以使用以下命令获取所有的g++标志和链接信息:
// pkg-config glfw3 glm glew --cflags --libs
//
// 使用以下命令编译:
// g++ main.cpp shader.cpp -I./ -IC:/msys64/mingw64/bin/../include -LC:/msys64/mingw64/bin/../lib -lglfw3 -lglew32 -o GLSLloader.exe

#include <cstdio>
#include <cstdlib>
#include <cstring>

#include <string>
#include <iostream>
#include <fstream>
#include <sstream>
#include <istream>
#include <ostream>

#include <map>
#include <vector>
#include <list>

extern "C" {
    #include <GL/glew.h>
    #include <GLFW/glfw3.h>
}

#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>

using ShaderUniforms = std::map<std::string, GLuint>;
class Shader {
private:
    ShaderUniforms uniforms;
    GLuint program;

    void LoadUniforms();
    GLuint Attachment(std::string filename, GLenum stype);

public:
    Shader();
    ~Shader();

    bool LoadProgram();
    void ReleaseProgram();
    void SetUniform(std::string key, const float data);

    void PrintUniforms();
};

#endif

shader.cpp

#include "shader.hpp"

// 代码改编自:https://learnopengl.com/Getting-started/Shaders

Shader::Shader() {
    program = 0;
    uniforms = ShaderUniforms();
}

Shader::~Shader() {
    ReleaseProgram();
}

bool Shader::LoadProgram() {
    char infoLog[512];
    bool success;
    int result;

    GLuint vertex = Attachment("vertex.glsl", GL_VERTEX_SHADER);
    GLuint fragment = Attachment("fragment.glsl", GL_FRAGMENT_SHADER);

    ReleaseProgram();

    program = glCreateProgram();
    success = true;

    glAttachShader(program, vertex);
    glAttachShader(program, fragment);

    glLinkProgram(program);
    glGetProgramiv(program, GL_LINK_STATUS, &result);

    if (!result) {
        glGetProgramInfoLog(program, 512, NULL, infoLog);
        std::cout << "SHADER::FAILED::LINK-PROGRAM " << infoLog << std::endl;
        success = false;
    }

    if (vertex != 0) {
        glDeleteShader(vertex);
    }

    if (fragment != 0) {
        glDeleteShader(fragment);
    }

    if (success) {
        LoadUniforms();
        return true;
    } else {
        return false;
    }
}

void Shader::ReleaseProgram() {
    if (program != 0) {
        glDeleteProgram(program);
        program = 0;
    }

    uniforms.clear();
}

void Shader::SetUniform(std::string key, const float data) {
    ShaderUniforms::iterator it;
    
    it = uniforms.find(key);
    if (it != uniforms.end()) {
        glUniform1f(it->second, data);
    }
}

// 私有
// 来源:https://stackoverflow.com

<details>
<summary>英文:</summary>

I don&#39;t know what you&#39;re doing wrong on your code, as you didn&#39;t provided a minimal reproducible example of your problem, so I can&#39;t point what you&#39;re doing it wrong.

By writing my own application to:
1. Load a GLFW window
2. Load OpenGL Context
3. Load a Shader based on your GLSL scripts (vertex and fragment)
4. Load all uniforms
5. Print all uniforms

That&#39;s the output of my application:

    SHADER: Loading uniforms
    (location = 0 ): light.intensity       &lt;- NOTE: This looks weird because
    (location = 1 ): light.position        i&#39;m not searching the correct location
    (location = 2 ): material.ka           id for each uniform name. I&#39;m guessing
    (location = 3 ): material.kd           them as if you&#39;ve never set the
    (location = 4 ): material.ks           locations manually. The print
    (location = 5 ): material.shininess    occurs inside a for-loop. If you
    (location = 6 ): normals_to_view_space take out all `layout(location=*)`
    (location = 7 ): to_screen_space       from the GLSL scripts, the ids printed
    (location = 8 ): to_view_space         here will look ok.

    SHADER: Printing Uniforms
    Uniform &#39;light.intensity&#39; location is (4)
    Uniform &#39;light.position&#39; location is (3)
    Uniform &#39;material.ka&#39; location is (6)
    Uniform &#39;material.kd&#39; location is (7)
    Uniform &#39;material.ks&#39; location is (8)
    Uniform &#39;material.shininess&#39; location is (9)
    Uniform &#39;normals_to_view_space&#39; location is (2)
    Uniform &#39;to_screen_space&#39; location is (0)
    Uniform &#39;to_view_space&#39; location is (1)

So, in my test application, the uniforms locations were loaded **successfully**.

Here&#39;s the code I used. Note I also use the OpenGL version 4.50, with Core Profile. My code is an adaptation of the code provided from the [learnopengl tutorials](https://learnopengl.com/):

**main.cpp**:

    #include &quot;shader.hpp&quot;

    int main(int argc, char **argv) {
        GLFWwindow* window = NULL;
        Shader shader;
        GLuint vao;

        glewExperimental = true;
        if (!glfwInit()) {
            std::cout &lt;&lt; &quot;GLFW::FAILED&quot; &lt;&lt; std::endl;
            return false;
        } else {
            glfwWindowHint(GLFW_SAMPLES, 4);
            glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4); // Our OpenGL version must be set 
            glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 5); // to 4.50 (same as the shader)
            glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
            glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

            window = glfwCreateWindow(800, 600, &quot;GLSLloader.exe&quot;, NULL, NULL);

            if (window == NULL) {
                std::cout &lt;&lt; &quot;GLFW::FAILED::CREATE::WINDOW&quot; &lt;&lt; std::endl;
                return false;
            } else {
                glfwMakeContextCurrent(window);

                if (glewInit() != GLEW_OK) {
                    std::cout &lt;&lt; &quot;GLEW::FAILED&quot; &lt;&lt; std::endl;
                } else {
                    glGenVertexArrays(1, &amp;vao);
                    glBindVertexArray(vao);

                    shader.LoadProgram();
                    shader.PrintUniforms();
                }
            }
        }

        return 0;
    }


**shader.hpp**:

    #ifndef _MY_SHADER_LOADER_
    #define _MY_SHADER_LOADER_

    // You can get all g++ flags and links by using the following command:
    // pkg-config glfw3 glm glew --cflags --libs
    // 
    // Compile with:
    // g++ main.cpp shader.cpp -I./ -IC:/msys64/mingw64/bin/../include -LC:/msys64/mingw64/bin/../lib -lglfw3 -lglew32 -o GLSLloader.exe

    #include &lt;cstdio&gt;
    #include &lt;cstdlib&gt;
    #include &lt;cstring&gt;

    #include &lt;string&gt;
    #include &lt;iostream&gt;
    #include &lt;fstream&gt;
    #include &lt;sstream&gt;
    #include &lt;istream&gt;
    #include &lt;ostream&gt;

    #include &lt;map&gt;
    #include &lt;vector&gt;
    #include &lt;list&gt;

    extern &quot;C&quot; {
        #include &lt;GL/glew.h&gt;
        #include &lt;GLFW/glfw3.h&gt;
    }

    #include &lt;glm/glm.hpp&gt;
    #include &lt;glm/gtc/matrix_transform.hpp&gt;

    using ShaderUniforms = std::map&lt;std::string, GLuint&gt;;
    class Shader {
    private:
        ShaderUniforms uniforms;
        GLuint program;

        void LoadUniforms();
        GLuint Attachment(std::string filename, GLenum stype);

    public:
        Shader();
        ~Shader();

        bool LoadProgram();
        void ReleaseProgram();
        void SetUniform(std::string key, const float data);

        void PrintUniforms();
    };

    #endif


**shader.cpp**:

    #include &quot;shader.hpp&quot;

    // Code adaptated from: https://learnopengl.com/Getting-started/Shaders

    Shader::Shader() {
        program = 0;
        uniforms = ShaderUniforms();
    }

    Shader::~Shader() {
        ReleaseProgram();
    }

    bool Shader::LoadProgram() {
        char infoLog[512];
        bool success;
        int result;

        GLuint vertex = Attachment(&quot;vertex.glsl&quot;, GL_VERTEX_SHADER);
        GLuint fragment = Attachment(&quot;fragment.glsl&quot;, GL_FRAGMENT_SHADER);

        ReleaseProgram();

        program = glCreateProgram();
        success = true;

        glAttachShader(program, vertex);
        glAttachShader(program, fragment);

        glLinkProgram(program);
        glGetProgramiv(program, GL_LINK_STATUS, &amp;result);

        if (!result) {
            glGetProgramInfoLog(program, 512, NULL, infoLog);
            std::cout &lt;&lt; &quot;SHADER::FAILED::LINK-PROGRAM &quot; &lt;&lt; infoLog &lt;&lt; std::endl;
            success = false;
        }

        if (vertex != 0) {
            glDeleteShader(vertex);
        }

        if (fragment != 0) {
            glDeleteShader(fragment);
        }

        if (success) {
            LoadUniforms();
            return true;
        } else {
            return false;
        }
    }

    void Shader::ReleaseProgram() {
        if (program != 0) {
            glDeleteProgram(program);
            program = 0;
        }

        uniforms.clear();
    }

    void Shader::SetUniform(std::string key, const float data) {
        ShaderUniforms::iterator it;
        
        it = uniforms.find(key);
        if (it != uniforms.end()) {
            glUniform1f(it-&gt;second, data);
        }
    }

    // Private
    // Source: https://stackoverflow.com/a/442819/14956120
    void Shader::LoadUniforms() {
        GLint n;
        GLint size;
        GLint bufSize;
        GLenum type;
        GLsizei length;
        std::string name;

        glGetProgramiv(program, GL_ACTIVE_UNIFORMS, &amp;n);
        glGetProgramiv(program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &amp;bufSize);

        std::vector&lt;GLchar&gt; uName = std::vector&lt;GLchar&gt;(bufSize+1, 0);

        std::cout &lt;&lt; &quot;SHADER: Loading uniforms&quot; &lt;&lt; std::endl;
        for (GLint i = 0; i &lt; n; ++i) {
            std::fill(uName.begin(), uName.end(), 0);
            glGetActiveUniform(program, i, bufSize, &amp;length, &amp;size, &amp;type, &amp;(uName[0]));
            if (length &gt; 0) {
                name = std::string(uName.begin(), uName.end());
                std::cout &lt;&lt; &quot;(location = &quot; &lt;&lt; i &lt;&lt; &quot; ): &quot; &lt;&lt; name &lt;&lt; std::endl;
                uniforms.insert(std::pair&lt;std::string, GLuint&gt;(name, (GLuint) i));
            }
        }
    }

    // Private
    GLuint Shader::Attachment(std::string filename, GLenum stype) {
        std::string code;
        std::ifstream file;
        std::stringstream stream;
        GLuint shader;
        char* ccode;
        char infoLog[512];
        int result;

        file.exceptions(std::ifstream::failbit | std::ifstream::badbit);

        try {
            file.open(filename);
            stream &lt;&lt; file.rdbuf();
            file.close();
            code = stream.str();
        } catch (std::ifstream::failure&amp; e) {
            std::cout &lt;&lt; &quot;SHADER::FAILED::READ::SOURCECODE (&quot; &lt;&lt; filename &lt;&lt; &quot;)&quot; &lt;&lt; std::endl;
            return 0;
        }

        shader = glCreateShader(stype);
        ccode = (char*) code.c_str();
        glShaderSource(shader, 1, (const GLchar**) &amp;(ccode), NULL);
        glCompileShader(shader);

        glGetShaderiv(shader, GL_COMPILE_STATUS, &amp;result);
        if (!result) {
            memset(infoLog, &#39;\0&#39;, sizeof(char) * 512);
            glGetShaderInfoLog(shader, 512, NULL, infoLog);
            std::cout &lt;&lt; &quot;SHADER::FAILED::COMPILE (&quot; &lt;&lt; filename &lt;&lt; &quot;): &quot; &lt;&lt; infoLog &lt;&lt; std::endl;
        }

        return shader;
    }

    // Used for testing only
    void Shader::PrintUniforms() {
        ShaderUniforms::iterator it;
        GLint location = -1;
        std::string name;

        std::cout &lt;&lt; std::endl;
        std::cout &lt;&lt; &quot;SHADER: Printing Uniforms&quot; &lt;&lt; std::endl;
        for (it = uniforms.begin(); it != uniforms.end(); ++it) {
            name = it-&gt;first;

            location = glGetUniformLocation(program, name.c_str());
            if (location == -1) {
                std::cout &lt;&lt; &quot;ERROR::SHADER::UNIFORM::&quot; &lt;&lt; name &lt;&lt; &quot;::NOT_FOUND&quot;&lt;&lt;std::endl;
                return;
            } else {
                std::cout &lt;&lt; &quot;Uniform &#39;&quot; &lt;&lt; name &lt;&lt; &quot;&#39; location is (&quot; &lt;&lt; location &lt;&lt; &quot;)&quot; &lt;&lt; std::endl;
            }
        }
    }


**vertex.glsl**:

    #version 450

    layout (location = 0) in vec3 pos;
    layout (location = 1) in vec3 norm;

    layout (location = 2) out vec3 v_space_norm;
    layout (location = 3) out vec3 v_space_pos;

    layout(location = 0) uniform mat4 to_screen_space; // mvp
    layout(location = 1) uniform mat4 to_view_space; //mv
    layout(location = 2) uniform mat3 normals_to_view_space;
    //layout(location = 4) float light_intensity;

    void main() {
        // for some reason, you wrote \* instead of *. So I removed the
        // backslash character as the GLSL compiler complained about it
        gl_Position = to_screen_space * vec4(pos, 1.0);
        v_space_norm = normals_to_view_space * norm;
        v_space_pos = (to_view_space * vec4(pos, 1.0)).xyz;
    }


**fragment.glsl**:

    #version 450
    precision mediump float;
    //------------ Structs ------------
    // struct Light{
    //      vec3 position;
    //      float intensity;
    // };

    //------------ Variying ------------
    layout (location = 2) in vec3 v_space_norm;
    layout (location = 3) in vec3 v_space_pos;

    //------------ Uniforms ------------
    layout(location = 1) uniform mat4 to_view_space; //mv
    //layout(location = 3) uniform vec3 light_position;

    //layout(location = 4) uniform float light_intensity;
    layout(location = 3) uniform struct{
         vec3 position;
         float intensity;
    }light;

    layout(location = 6) uniform struct{
         vec3 ka;
         vec3 kd;
         vec3 ks;
         float shininess;
    } material;


    out vec4 color;

    void main() {
         vec3 v_space_norm = normalize(v_space_norm);
         vec3 l =  normalize( (to_view_space * vec4(light.position, 1)).xyz - v_space_pos);//normalize(l); //light vector
         vec3 h = normalize(l + vec3(0,0,1)); //half vector

         float cos_theta = dot(l, v_space_norm);
         if(cos_theta &gt;= 0)
         {
              vec3 diffuse = material.kd * max(cos_theta,0);
              vec3 ambient = material.ka;
              vec3 specular= material.ks * pow(max(dot(h, v_space_norm),0), material.shininess);
              color = vec4(light.intensity * (specular + diffuse) + ambient, 1);
         }
         else
         {
              color = vec4(material.ka,1);
         }
    }


---

Here&#39;s my project structure:

    .
    ├── main.cpp
    ├── shader.hpp
    ├── shader.cpp
    ├── vertex.glsl
    └── fragment.glsl

I&#39;m using MSYS2 on windows 10, to compile and run the application.


</details>



huangapple
  • 本文由 发表于 2023年2月6日 09:31:26
  • 转载请务必保留本文链接:https://go.coder-hub.com/75356651.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定