【问题标题】:How I can avoid in OpenGL disappearing lines using a shader?如何避免使用着色器在 OpenGL 中消失线?
【发布时间】:2021-01-12 23:04:21
【问题描述】:

所以我只使用片段着色器来绘制一些线条。顶点只是一个空的四边形。

我遇到的问题是,当我缩小相机并且线条变小时,它们有时会出现又消失,我不明白为什么。

这是不缩放的样子

这就是相机远离他们时的样子

我离他们越远,出现的人工制品就越多。

这就是我的顶点着色器的样子

#version 330 core

layout(location = 0) in vec2 _position;

out vec2 position;

uniform mat4 uCameraView;

void main() {
  gl_Position = uCameraView * vec4(_position.x, _position.y, 0.0f, 1.0f);
  position = _position;
}

这是片段

#version 330 core

in vec2 position;

uniform vec4 uGridColor;
uniform float uTileSize;
uniform float uGridBorderSize;

out vec4 fragColor;

void main() {
  vec2 uv = mod(position, uTileSize);
  vec2 border = mod(uv + (uGridBorderSize / 2.0), uTileSize);
  border -= mod(uv - (uGridBorderSize / 2.0), uTileSize);

  if (length(border) > uTileSize - uGridBorderSize) {
    fragColor = uGridColor;
  } else {
    fragColor = vec4(0.0);
  }
}

为什么会这样?也许与抗锯齿有关?我的 OpenGL 设置只是默认设置。

【问题讨论】:

  • 你想要的是某种抗锯齿。
  • 我该怎么做?
  • 我们可以看一下C++代码吗?乍一看有点难以分辨,但使用完整的代码库可能会更清楚。
  • 我敢打赌,你现在需要有恒定的线宽(不管缩放)你在取消缩放时遇到问题,线将小于像素粗,这有时会由于锯齿效应导致不可见的线条(可见和不可见是位置的函数)。你的图像显示你的线条有 +/-1 不同的粗细,它是一样的......将它应用到你的支票上......这是有问题的,因为我们不知道什么变量是什么以及具有什么值,范围等。您还应该以像素为单位传递视图分辨率,因为这将需要...
  • 线条消失的原因是它们变得小于一个像素。在这种情况下你希望发生什么?通常有两种方法来解决这个问题:1)不允许线条粗细小于 1 像素,2)如果线条比背景颜色细 1 像素 lerp。所以在你的情况下,当线条变得小于 1 像素时,会变成灰色

标签: c++ opengl glsl


【解决方案1】:

您当前的代码正在做出“是行”/“否行”的二元决定。但是,超出某个点(线宽

您需要计算像素覆盖率,即像素内有多少行,而不是使用二进制“是”/“否”。为此,您通常会使用无符号距离函数 (UDF)。这是像素空间中 UDF 线的一些 GLSL 代码(您也可以在标准化空间中使用它们,但是您必须调整平滑步长参数)。试试这个https://shadertoy.com

float lsd(vec2 a, vec2 b, vec2 p, float w){
    w *= 0.5;
    vec2  n = normalize(b-a);
    float l = length(b-a);
    float t = dot((p-a),n);
    float d = length((a-p)+t*n);
    float e = min(length(p-a)+w, length(p-b)+w);
    return (t > w && t < l-w) ? d : e;
}

float line(vec2 a, vec2 b, float width, vec2 fragcoord){
    return max(0., 1.-smoothstep(0., 1., lsd(a, b, fragcoord, width)-0.5*width));
}

void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
    float l =
          line(vec2(8.,8.), vec2(128.,33.), 1., fragCoord)
        + line(vec2(33.,220.), vec2(260.,20.), 4., fragCoord);
    fragColor = vec4(l,l,l,1.0);
}

【讨论】:

    【解决方案2】:

    仅根据您的着色器很难判断,因此这里有一个如何围绕线网格进行缩放和平移的示例。它使用投影矩阵进行缩放,看起来与您实现缩放的方式略有不同,但重要的是它在缩放/平移时没有任何线条变细的伪影。

    这是一个演示,希望 GIF 显示它,但是当您放大和缩小时,网格线的粗细是恒定的:

    #include <iostream>
    #include <vector>
    
    #include <glad/glad.h>
    #include <GLFW/glfw3.h>
    #define GLM_ENABLE_EXPERIMENTAL
    #include <glm/glm.hpp>
    #include <glm/gtc/matrix_transform.hpp>
    #include <glm/gtx/string_cast.hpp>
    
    using std::vector;
    using glm::mat4;
    using glm::vec3;
    using glm::vec4;
    
    void processInput(GLFWwindow *window);
    void mouse_callback(GLFWwindow* window, double xpos, double ypos);
    void scroll_callback(GLFWwindow* window, double xoffset, double yoffset);
    
    // settings
    const unsigned int SCR_WIDTH = 800;
    const unsigned int SCR_HEIGHT = 600;
    
    float lastX = SCR_WIDTH / 2.0f;
    float lastY = SCR_HEIGHT / 2.0f;
    bool firstMouse = true;
    
    // timing
    float deltaTime = 0.0f;
    float lastFrame = 0.0f;
    
    vec3 rayCast(double xpos, double ypos, mat4 projection, mat4 view) {
        // converts a position from the 2d xpos, ypos to a normalized 3d direction
        float x = (2.0f * xpos) / SCR_WIDTH - 1.0f;
        float y = 1.0f - (2.0f * ypos) / SCR_HEIGHT;
        float z = 1.0f;
        vec3 ray_nds = vec3(x, y, z);
        vec4 ray_clip = vec4(ray_nds.x, ray_nds.y, -1.0f, 1.0f);
        // eye space to clip we would multiply by projection so
        // clip space to eye space is the inverse projection
        vec4 ray_eye = inverse(projection) * ray_clip;
        // convert point to forwards
        ray_eye = vec4(ray_eye.x, ray_eye.y, -1.0f, 0.0f);
        // world space to eye space is usually multiply by view so
        // eye space to world space is inverse view
        vec4 inv_ray_wor = (inverse(view) * ray_eye);
        vec3 ray_wor = vec3(inv_ray_wor.x, inv_ray_wor.y, inv_ray_wor.z);
        ray_wor = normalize(ray_wor);
        return ray_wor;
    }
    
    class Line {
        int shaderProgram;
        unsigned int VBO, VAO;
        vector<float> vertices;
        vec3 startPoint;
        vec3 endPoint;
        mat4 MVP;
        vec3 lineColor;
    public:
        Line(vec3 start, vec3 end) {
    
            startPoint = start;
            endPoint = end;
            lineColor = vec3(1,1,1);
    
            const char *vertexShaderSource = "#version 330 core\n"
                "layout (location = 0) in vec3 aPos;\n"
                "uniform mat4 MVP;\n"
                "void main()\n"
                "{\n"
                "   gl_Position = MVP * vec4(aPos.x, aPos.y, aPos.z, 1.0);\n"
                "}\0";
            const char *fragmentShaderSource = "#version 330 core\n"
                "out vec4 FragColor;\n"
                "uniform vec3 color;\n"
                "void main()\n"
                "{\n"
                "   FragColor = vec4(color, 1.0f);\n"
                "}\n\0";
    
            // vertex shader
            int vertexShader = glCreateShader(GL_VERTEX_SHADER);
            glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
            glCompileShader(vertexShader);
            // check for shader compile errors
            int success;
            char infoLog[512];
            glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
            if (!success)
            {
                glGetShaderInfoLog(vertexShader, 512, NULL, infoLog);
                std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << std::endl;
            }
            // fragment shader
            int fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
            glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
            glCompileShader(fragmentShader);
            // check for shader compile errors
            glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);
            if (!success)
            {
                glGetShaderInfoLog(fragmentShader, 512, NULL, infoLog);
                std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infoLog << std::endl;
            }
            // link shaders
            shaderProgram = glCreateProgram();
            glAttachShader(shaderProgram, vertexShader);
            glAttachShader(shaderProgram, fragmentShader);
            glLinkProgram(shaderProgram);
            // check for linking errors
            glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success);
            if (!success) {
                glGetProgramInfoLog(shaderProgram, 512, NULL, infoLog);
                std::cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << infoLog << std::endl;
            }
            glDeleteShader(vertexShader);
            glDeleteShader(fragmentShader);
    
            vertices = {
                 start.x, start.y, start.z,
                 end.x, end.y, end.z,
    
            };
            
            glGenVertexArrays(1, &VAO);
            glGenBuffers(1, &VBO);
            glBindVertexArray(VAO);
    
            glBindBuffer(GL_ARRAY_BUFFER, VBO);
            glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices.data(), GL_STATIC_DRAW);
    
            glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
            glEnableVertexAttribArray(0);
    
            glBindBuffer(GL_ARRAY_BUFFER, 0); 
            glBindVertexArray(0); 
    
        }
    
        int setMVP(mat4 mvp) {
            MVP = mvp;
        }
    
        int setColor(vec3 color) {
            lineColor = color;
        }
    
        int draw() {
            glUseProgram(shaderProgram);
            glUniformMatrix4fv(glGetUniformLocation(shaderProgram, "MVP"), 1, GL_FALSE, &MVP[0][0]);
            glUniform3fv(glGetUniformLocation(shaderProgram, "color"), 1, &lineColor[0]);
    
            glBindVertexArray(VAO);
            glDrawArrays(GL_LINES, 0, 2);
            return 0;
        }
    
        ~Line() {
            // optional: de-allocate all resources once they've outlived their purpose:
            // ------------------------------------------------------------------------
            glDeleteVertexArrays(1, &VAO);
            glDeleteBuffers(1, &VBO);
            glDeleteProgram(shaderProgram);
        }
    };
    
    vec3 cameraPos = glm::vec3(0.0f, 0.0f, 15.0f);
    vec3 cameraFront = glm::vec3(0,0,-1);
    mat4 model = mat4(1.0);
    glm::mat4 view;
    glm::mat4 projection;
    float scrollSpeed = 2.0f;
    float fov = 45.0f;
    
    int main()
    {
    
        glfwInit();
        glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
        glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
        glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
    
    #ifdef __APPLE__
        glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
    #endif
    
        GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "grid", NULL, NULL);
        if (window == NULL)
        {
            std::cout << "Failed to create GLFW window" << std::endl;
            glfwTerminate();
            return -1;
        }
        glfwMakeContextCurrent(window);
        glfwSetCursorPosCallback(window, mouse_callback);
        glfwSetScrollCallback(window, scroll_callback);
    
        if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
        {
            std::cout << "Failed to initialize GLAD" << std::endl;
            return -1;
        }
    
        Line x(vec3(0,0,0), vec3(1,0,0));
        x.setColor(vec3(1,0,0));
        Line y(vec3(0,0,0), vec3(0,1,0));
        y.setColor(vec3(0,1,0));
    
        std::vector<Line*> grid = {};
        for (int i = -5; i < 6; i++) {
            grid.push_back(new Line(vec3(-5, i, 0), vec3(5,i, 0)));
        }
        for (int j = -5; j < 6; j++) {
            grid.push_back(new Line(vec3(j, -5, 0), vec3(j,5, 0)));
        };
    
        while (!glfwWindowShouldClose(window))
        {
    
            if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
                glfwSetWindowShouldClose(window, true);
    
            float currentFrame = glfwGetTime();
            deltaTime = currentFrame - lastFrame;
            lastFrame = currentFrame;
    
            glClearColor(0.0, 0.0, 0.0, 1.0);
            glClear(GL_COLOR_BUFFER_BIT);
    
            view = glm::lookAt(cameraPos,  cameraPos + cameraFront, vec3(0,1,0));
    
            projection = glm::perspective(glm::radians(fov), (float)SCR_WIDTH / (float)SCR_HEIGHT, 0.1f, 100.0f);
    
            for (int i = 0; i < grid.size(); i++) {
                grid[i]->setMVP(projection * view * model);
                grid[i]->draw();
            }
    
            glfwSwapBuffers(window);
            glfwPollEvents();
        }
        for (int i = 0; i < grid.size(); i++) {
            delete grid.at(i);
        }
        glfwTerminate();
        return 0;
    }
    
    void processInput(GLFWwindow *window)
    {
        if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
            glfwSetWindowShouldClose(window, true);
    }
    
    
    void mouse_callback(GLFWwindow* window, double xpos, double ypos)
    {
    
        if (firstMouse)
        {
            lastX = xpos;
            lastY = ypos;
            firstMouse = false;
        }
    
        float xoffset = xpos - lastX;
        float yoffset = lastY - ypos; 
    
        lastX = xpos;
        lastY = ypos;
    
    
        int state = glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_MIDDLE);
        if (state == GLFW_PRESS)
        {
            glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
            cameraPos -= scrollSpeed * glm::vec3(xoffset/(float)SCR_WIDTH, yoffset/(float)SCR_WIDTH, 0);
    
        } else {
            glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
            firstMouse = true;
        }
    }
    
    void scroll_callback(GLFWwindow* window, double xoffset, double yoffset)
    {
        cameraPos += (float)yoffset * rayCast(lastX, lastY, projection, view);
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-09-03
      • 1970-01-01
      • 2019-09-19
      • 2014-06-17
      • 2014-06-03
      • 1970-01-01
      • 2015-06-15
      相关资源
      最近更新 更多