gpt4 book ai didi

c++ - 曲面 segmentation 着色器没有输出?

转载 作者:太空狗 更新时间:2023-10-29 21:34:02 28 4
gpt4 key购买 nike

我一直在研究地形 LOD 算法,但主要逻辑在 CPU 上:

CPU based terrain LOD

我尝试将大部分逻辑转换为 opengl 管道的曲面 segmentation 控制和评估阶段,但没有任何显示:

GPU based terrain LOD?

我将代码缩减为基本的“hello quad”程序

#define GLEW_STATIC
#include <glew.h>
#include <glfw3.h>
#include <glm.hpp>
#include <gtc/matrix_transform.hpp>
#include <stdio.h>
#include <string>
#include <stdlib.h>
#include <string.h>
#include <vector>
#include <iostream>
#include <fstream>
#include <algorithm>

using namespace std;

/* Shader Source */

// vertex shader
const GLchar * VS_src[] = {
"#version 430\n"

"layout(location = 0) in vec3 position;\n"
"out vec4 vposition;\n"

"void main()\n"
"{\n"
" vposition = vec4(position, 1.0);\n"
"}\n"
};

// tesselation control shader
const GLchar * TCS_src[] = {
"#version 430\n"

"layout(vertices = 4) out;\n"
"in vec4 vposition[];\n"
"out vec4 tposition[];\n"

"void main()\n"
"{\n"
" tposition[gl_InvocationID] = vposition[gl_InvocationID];\n"

" if (gl_InvocationID == 0)\n"
" {\n"
" float tessLevel = 1.0;\n"

" gl_TessLevelInner[0] = tessLevel;\n"
" gl_TessLevelInner[1] = tessLevel;\n"

" gl_TessLevelOuter[0] = tessLevel;\n"
" gl_TessLevelOuter[1] = tessLevel;\n"
" gl_TessLevelOuter[2] = tessLevel;\n"
" gl_TessLevelOuter[3] = tessLevel;\n"
" }\n"
"}\n"
};

// tesselation evaluation shader
const GLchar * TES_src[] = {
"#version 430\n"

"uniform mat4 mvp;\n"
"layout(quads) in;\n"
"in vec4 tposition[];\n"

"void main()\n"
"{\n"
" float x = gl_TessCoord[0] * (tposition[1].x - tposition[0].x) + tposition[0].x;\n"
" float z = gl_TessCoord[2] * (tposition[1].z - tposition[2].z) + tposition[2].z;\n"
" float y = 0.0;\n"

" gl_Position = mvp * vec4(x, y, z, 1.0);\n"

"}\n"
};

// fragment shader
const GLchar * FS_src[] = {
"#version 430\n"

"out vec3 color;\n"

"void main()\n"
"{\n"
"color = vec3(0.0);\n"
"}\n"
};

/* Link Shaders to Program */

GLuint LoadShaders(const GLchar ** VS, const GLchar ** TCS, const GLchar ** TES, const GLchar ** FS)
{

// Create the shaders
GLuint VS_ID = glCreateShader(GL_VERTEX_SHADER);
GLuint TCS_ID = glCreateShader(GL_TESS_CONTROL_SHADER);
GLuint TES_ID = glCreateShader(GL_TESS_EVALUATION_SHADER);
GLuint FS_ID = glCreateShader(GL_FRAGMENT_SHADER);

GLint Result = GL_FALSE;
int InfoLogLength;

// Compile Vertex Shader
printf("compiling vertex shader\n");
glShaderSource(VS_ID, 1, VS, NULL);
glCompileShader(VS_ID);

// Check Vertex Shader
glGetShaderiv(VS_ID, GL_COMPILE_STATUS, &Result);
glGetShaderiv(VS_ID, GL_INFO_LOG_LENGTH, &InfoLogLength);
if ( InfoLogLength > 0 ){
std::vector<char> VertexShaderErrorMessage(InfoLogLength+1);
glGetShaderInfoLog(VS_ID, InfoLogLength, NULL, &VertexShaderErrorMessage[0]);
printf("%s\n", &VertexShaderErrorMessage[0]);
}

// Compile Tess Control Shader
printf("compiling tesselation control shader\n");
glShaderSource(TCS_ID, 1, TCS, NULL);
glCompileShader(TCS_ID);

// Check Tess Control Shader
glGetShaderiv(TCS_ID, GL_COMPILE_STATUS, &Result);
glGetShaderiv(TCS_ID, GL_INFO_LOG_LENGTH, &InfoLogLength);
if ( InfoLogLength > 0 ){
std::vector<char> TessControlShaderErrorMessage(InfoLogLength+1);
glGetShaderInfoLog(TCS_ID, InfoLogLength, NULL, &TessControlShaderErrorMessage[0]);
printf("%s\n", &TessControlShaderErrorMessage[0]);
}

// Compile Tess Evaluation Shader
printf("compiling tesselation evaluation shader\n");
glShaderSource(TES_ID, 1, TES, NULL);
glCompileShader(TES_ID);

// Check Tess Evaluation Shader
glGetShaderiv(TES_ID, GL_COMPILE_STATUS, &Result);
glGetShaderiv(TES_ID, GL_INFO_LOG_LENGTH, &InfoLogLength);
if ( InfoLogLength > 0 ){
std::vector<char> TessEvaluationShaderErrorMessage(InfoLogLength+1);
glGetShaderInfoLog(TES_ID, InfoLogLength, NULL, &TessEvaluationShaderErrorMessage[0]);
printf("%s\n", &TessEvaluationShaderErrorMessage[0]);
}

// Compile Fragment Shader
printf("compiling fragment shader\n");
glShaderSource(FS_ID, 1, FS, NULL);
glCompileShader(FS_ID);

// Check Fragment Shader
glGetShaderiv(FS_ID, GL_COMPILE_STATUS, &Result);
glGetShaderiv(FS_ID, GL_INFO_LOG_LENGTH, &InfoLogLength);
if ( InfoLogLength > 0 ){
std::vector<char> FragmentShaderErrorMessage(InfoLogLength+1);
glGetShaderInfoLog(FS_ID, InfoLogLength, NULL, &FragmentShaderErrorMessage[0]);
printf("%s\n", &FragmentShaderErrorMessage[0]);
}

// Link the program
printf("linking program\n");
GLuint ProgramID = glCreateProgram();

glAttachShader(ProgramID, VS_ID);
glAttachShader(ProgramID, TCS_ID);
glAttachShader(ProgramID, TES_ID);
glAttachShader(ProgramID, FS_ID);

glLinkProgram(ProgramID);

// Check the program
glGetProgramiv(ProgramID, GL_LINK_STATUS, &Result);
glGetProgramiv(ProgramID, GL_INFO_LOG_LENGTH, &InfoLogLength);
if ( InfoLogLength > 0 ){
std::vector<char> ProgramErrorMessage(InfoLogLength+1);
glGetProgramInfoLog(ProgramID, InfoLogLength, NULL, &ProgramErrorMessage[0]);
printf("%s\n", &ProgramErrorMessage[0]);
}

glDetachShader(ProgramID, VS_ID);
glDetachShader(ProgramID, TCS_ID);
glDetachShader(ProgramID, TES_ID);
glDetachShader(ProgramID, FS_ID);

glDeleteShader(VS_ID);
glDeleteShader(TCS_ID);
glDeleteShader(TES_ID);
glDeleteShader(FS_ID);

return ProgramID;
}

/* MAIN */
int main()
{
GLFWwindow * window;

if (!glfwInit()) return 0;

glfwWindowHint(GLFW_SAMPLES, 0);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

window = glfwCreateWindow(1600, 900, "Test", NULL, NULL);
if (!window) return 0;

glfwMakeContextCurrent(window);
glfwSetInputMode(window, GLFW_STICKY_KEYS, GL_TRUE);

glewExperimental=true;
if (glewInit() != GLEW_OK) return 0;

// Init
glm::mat4 p = glm::perspective(glm::radians(45.0f), 1600.0f / 900.0f, 0.1f, 1000.0f);
// look at <0,0,0> from <20,20,20>
glm::mat4 v = glm::lookAt(glm::vec3(20.0f), glm::vec3(0.0f), glm::vec3(0,1,0));
glm::mat4 m = glm::mat4(1.0f);
glm::mat4 mvp = p * v * m;

// draw 1 quad
std::vector<unsigned int> indices;
std::vector<glm::vec3> vertices;

indices.push_back(0);
indices.push_back(1);
indices.push_back(2);
indices.push_back(3);

vertices.push_back(glm::vec3(-10.0f, 0.0f, -10.0f));
vertices.push_back(glm::vec3( 10.0f, 0.0f, -10.0f));
vertices.push_back(glm::vec3( 10.0f, 0.0f, 10.0f));
vertices.push_back(glm::vec3(-10.0f, 0.0f, 10.0f));

// VAO
GLuint VertexArrayID;
glGenVertexArrays(1, &VertexArrayID);
glBindVertexArray(VertexArrayID);

// program
GLuint ProgramID = LoadShaders(VS_src, TCS_src, TES_src, FS_src);

// mvp uniform
GLuint MatrixID = glGetUniformLocation(ProgramID, "mvp");

// Vertex Buffer
GLuint vertexbuffer;
glGenBuffers(1, &vertexbuffer);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(glm::vec3), &vertices[0], GL_STATIC_DRAW);

// Element Buffer
GLuint elementbuffer;
glGenBuffers(1, &elementbuffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementbuffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(unsigned int), &indices[0], GL_STATIC_DRAW);

// loop
while( glfwGetKey(window, GLFW_KEY_ESCAPE ) != GLFW_PRESS && glfwWindowShouldClose(window) == 0 )
{
glViewport(0, 0, 1600, 900);
glClearColor(0.478f, 0.702f, 0.816f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

glDisable(GL_DEPTH_TEST);
glDisable(GL_CULL_FACE);

glUseProgram(ProgramID);

glUniformMatrix4fv(MatrixID, 1, GL_FALSE, &mvp[0][0]);

glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);

glPatchParameteri(GL_PATCH_VERTICES, 4);

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementbuffer);
glDrawElements(GL_PATCHES, indices.size(), GL_UNSIGNED_INT, (void*)0);

glDisableVertexAttribArray(0);

glfwSwapBuffers(window);
glfwPollEvents();
}

// cleanup
glDeleteVertexArrays(1, &VertexArrayID);
glDeleteProgram(ProgramID);
glDeleteBuffers(1, &vertexbuffer);
glDeleteBuffers(1, &elementbuffer);

glfwTerminate();

return 0;
}

但仍然没有显示任何内容(除了蓝色透明背景)。所有着色器编译无错,程序链接无错。

最佳答案

当使用 quads 原始模式时,只有 gl_TessCoord 的前 2 个组件有意义。第三个分量是 0.0。 gl_TessCoord[0]gl_TessCoord[1] 提供标准化的二维坐标,类似于纹理的 UV 坐标。

这意味着您必须在曲面 segmentation 评估着色器中使用 gl_TessCoord[1] 而不是 gl_TessCoord[2]:

float x = gl_TessCoord[0] * (tposition[1].x - tposition[0].x) + tposition[0].x;
float z = gl_TessCoord[1] * (tposition[1].z - tposition[2].z) + tposition[2].z;

参见 Tessellation, Quads


规范:

GLSL - The OpenGL Shading Language 4.6, 7.1 Built-In Language Variables, page 129 :

The variable gl_TessCoord is available only in the tessellation evaluation language. It specifies a threecomponent (u,v,w) vector identifying the position of the vertex being processed by the shader relative to the primitive being tessellated.

OpenGL 4.6 core profile specification, 11.2.2.2 Quad Tessellation, page 416 :

If the tessellation primitive mode is quads, a rectangle is subdivided into a collection of triangles covering the area of the original rectangle. First, the original rectangle is subdivided into a regular mesh of rectangles, where the number of rectangles along the u = 0 and u = 1 (vertical) and v = 0 and v = 1 (horizontal) edges are derived from the first and second inner tessellation levels, respectively.

关于c++ - 曲面 segmentation 着色器没有输出?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48470881/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com