Switch triangle for tessellated quad patch with tess shaders
This commit is contained in:
parent
250c108e97
commit
b2450d4ca5
|
@ -6,6 +6,7 @@
|
||||||
GLuint InitShader( const char* computeShaderFile);
|
GLuint InitShader( const char* computeShaderFile);
|
||||||
GLuint InitShader( const char* vertexShaderFile, const char* fragmentShaderFile );
|
GLuint InitShader( const char* vertexShaderFile, const char* fragmentShaderFile );
|
||||||
GLuint InitShader( const char* vertexShaderFile, const char* geometryShader, const char* fragmentShaderFile );
|
GLuint InitShader( const char* vertexShaderFile, const char* geometryShader, const char* fragmentShaderFile );
|
||||||
|
GLuint InitShader( const char* vShaderFile, const char* tcShader, const char* teShader, const char* fShaderFile );
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
|
@ -33,6 +33,8 @@ in VertexData
|
||||||
vec3 nw; //world-space normal vector
|
vec3 nw; //world-space normal vector
|
||||||
} inData; //block is named 'inData'
|
} inData; //block is named 'inData'
|
||||||
|
|
||||||
|
in vec3 frag_position;
|
||||||
|
|
||||||
out vec4 frag_color; //the output color for this fragment
|
out vec4 frag_color; //the output color for this fragment
|
||||||
|
|
||||||
void main(void)
|
void main(void)
|
||||||
|
@ -56,6 +58,6 @@ void main(void)
|
||||||
// vec4 specular_term = atten*ks*Ls*pow(max(0.0, dot(rw, vw)), shininess);
|
// vec4 specular_term = atten*ks*Ls*pow(max(0.0, dot(rw, vw)), shininess);
|
||||||
|
|
||||||
// fragcolor = ambient_term + diffuse_term + specular_term;
|
// fragcolor = ambient_term + diffuse_term + specular_term;
|
||||||
frag_color = vec4(0.45f, 0.82f, 0.52f, 1.0f);
|
frag_color = vec4(frag_position, 1.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
#version 430
|
||||||
|
|
||||||
|
layout(vertices = 4) out; // Define the number of control points per patch (e.g., 4 for a quad)
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
// Pass through control points to the tessellation evaluation shader
|
||||||
|
gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;
|
||||||
|
|
||||||
|
// Set the tessellation levels (outer and inner)
|
||||||
|
if (gl_InvocationID == 0) {
|
||||||
|
gl_TessLevelOuter[0] = 5.0; // Level of tessellation along one edge
|
||||||
|
gl_TessLevelOuter[1] = 5.0; // Level of tessellation along another edge
|
||||||
|
gl_TessLevelOuter[2] = 5.0; // Level of tessellation along the other edge
|
||||||
|
gl_TessLevelOuter[3] = 5.0; // Level of tessellation along the other edge
|
||||||
|
gl_TessLevelInner[0] = 5.0; // Level of tessellation for the inner part
|
||||||
|
gl_TessLevelInner[1] = 5.0; // Level of tessellation for the inner part
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
#version 430
|
||||||
|
|
||||||
|
layout(quads, equal_spacing, ccw) in; // Define the type of patch (e.g., quads)
|
||||||
|
|
||||||
|
out vec3 frag_position; // Ensure this matches the input in fragment.glsl
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
// Interpolate the position using the barycentric coordinates from tessellation
|
||||||
|
vec3 pos = mix(mix(gl_in[0].gl_Position.xyz, gl_in[1].gl_Position.xyz, gl_TessCoord.x),
|
||||||
|
mix(gl_in[3].gl_Position.xyz, gl_in[2].gl_Position.xyz, gl_TessCoord.x),
|
||||||
|
gl_TessCoord.y);
|
||||||
|
|
||||||
|
frag_position = pos;
|
||||||
|
|
||||||
|
gl_Position = vec4(pos, 1.0);
|
||||||
|
}
|
|
@ -1,30 +1,41 @@
|
||||||
#version 430
|
#version 430
|
||||||
layout(location = 0) uniform mat4 M;
|
|
||||||
layout(location = 1) uniform float time;
|
|
||||||
|
|
||||||
layout(std140, binding = 0) uniform SceneUniforms
|
layout(location = 0) in vec3 pos_attrib;
|
||||||
{
|
|
||||||
mat4 PV; //camera projection * view matrix
|
|
||||||
vec4 eye_w; //world-space eye position
|
|
||||||
};
|
|
||||||
|
|
||||||
layout(location = 0) in vec3 pos_attrib; //this variable holds the position of mesh vertices
|
|
||||||
layout(location = 1) in vec2 tex_coord_attrib;
|
layout(location = 1) in vec2 tex_coord_attrib;
|
||||||
layout(location = 2) in vec3 normal_attrib;
|
layout(location = 2) in vec3 normal_attrib;
|
||||||
|
|
||||||
out VertexData
|
void main() {
|
||||||
{
|
gl_Position = vec4(pos_attrib, 1.0);
|
||||||
vec2 tex_coord;
|
}
|
||||||
vec3 pw; //world-space vertex position
|
|
||||||
vec3 nw; //world-space normal vector
|
|
||||||
} outData;
|
|
||||||
|
|
||||||
void main(void)
|
|
||||||
{
|
// #version 400 core
|
||||||
gl_Position = PV*M*vec4(pos_attrib, 1.0); //transform vertices and send result into pipeline
|
// layout(location = 0) uniform mat4 M;
|
||||||
|
// layout(location = 1) uniform float time;
|
||||||
|
|
||||||
|
// layout(std140, binding = 0) uniform SceneUniforms
|
||||||
|
// {
|
||||||
|
// mat4 PV; //camera projection * view matrix
|
||||||
|
// vec4 eye_w; //world-space eye position
|
||||||
|
// };
|
||||||
|
|
||||||
|
// layout(location = 0) in vec3 pos_attrib; //this variable holds the position of mesh vertices
|
||||||
|
// layout(location = 1) in vec2 tex_coord_attrib;
|
||||||
|
// layout(location = 2) in vec3 normal_attrib;
|
||||||
|
|
||||||
|
// out VertexData
|
||||||
|
// {
|
||||||
|
// vec2 tex_coord;
|
||||||
|
// vec3 pw; //world-space vertex position
|
||||||
|
// vec3 nw; //world-space normal vector
|
||||||
|
// } outData;
|
||||||
|
|
||||||
|
// void main(void)
|
||||||
|
// {
|
||||||
|
// gl_Position = PV*M*vec4(pos_attrib, 1.0); //transform vertices and send result into pipeline
|
||||||
|
|
||||||
//Use dot notation to access members of the interface block
|
// //Use dot notation to access members of the interface block
|
||||||
outData.tex_coord = tex_coord_attrib; //send tex_coord to fragment shader
|
// outData.tex_coord = tex_coord_attrib; //send tex_coord to fragment shader
|
||||||
outData.pw = vec3(M*vec4(pos_attrib, 1.0)); //world-space vertex position
|
// outData.pw = vec3(M*vec4(pos_attrib, 1.0)); //world-space vertex position
|
||||||
outData.nw = vec3(M*vec4(normal_attrib, 0.0)); //world-space normal vector
|
// outData.nw = vec3(M*vec4(normal_attrib, 0.0)); //world-space normal vector
|
||||||
}
|
// }
|
|
@ -269,3 +269,72 @@ GLuint InitShader(const char* vShaderFile, const char* gShaderFile, const char*
|
||||||
|
|
||||||
return program;
|
return program;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GLuint InitShader( const char* vShaderFile, const char* tcShader, const char* teShader, const char* fShaderFile )
|
||||||
|
{
|
||||||
|
bool error = false;
|
||||||
|
struct Shader
|
||||||
|
{
|
||||||
|
const char* filename;
|
||||||
|
GLenum type;
|
||||||
|
std::string source;
|
||||||
|
} shaders[4] =
|
||||||
|
{
|
||||||
|
{ vShaderFile, GL_VERTEX_SHADER, "" },
|
||||||
|
{ tcShader, GL_TESS_CONTROL_SHADER, "" },
|
||||||
|
{ teShader, GL_TESS_EVALUATION_SHADER, "" },
|
||||||
|
{ fShaderFile, GL_FRAGMENT_SHADER, "" }
|
||||||
|
};
|
||||||
|
|
||||||
|
GLuint program = glCreateProgram();
|
||||||
|
|
||||||
|
for ( int i = 0; i < 4; ++i )
|
||||||
|
{
|
||||||
|
Shader& s = shaders[i];
|
||||||
|
s.source = readShaderSource(s.filename);
|
||||||
|
if ( shaders[i].source.length() == 0 )
|
||||||
|
{
|
||||||
|
std::cerr << "Failed to read " << s.filename << std::endl;
|
||||||
|
error = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLuint shader = glCreateShader( s.type );
|
||||||
|
const char *c_str = s.source.c_str();
|
||||||
|
glShaderSource(shader, 1, (const GLchar**)&c_str, NULL);
|
||||||
|
glCompileShader( shader );
|
||||||
|
|
||||||
|
GLint compiled;
|
||||||
|
glGetShaderiv( shader, GL_COMPILE_STATUS, &compiled );
|
||||||
|
if ( !compiled )
|
||||||
|
{
|
||||||
|
std::cerr << s.filename << " failed to compile:" << std::endl;
|
||||||
|
printShaderCompileError(shader);
|
||||||
|
error = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
glAttachShader( program, shader );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* link and error check */
|
||||||
|
glLinkProgram(program);
|
||||||
|
|
||||||
|
GLint linked;
|
||||||
|
glGetProgramiv( program, GL_LINK_STATUS, &linked );
|
||||||
|
if ( !linked )
|
||||||
|
{
|
||||||
|
std::cerr << "Shader program failed to link" << std::endl;
|
||||||
|
printProgramLinkError(program);
|
||||||
|
|
||||||
|
error = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(error == true)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* use program object */
|
||||||
|
glUseProgram(program);
|
||||||
|
|
||||||
|
return program;
|
||||||
|
}
|
|
@ -25,6 +25,8 @@
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
const std::string kVertexShaderPath = "shaders/vertex.glsl";
|
const std::string kVertexShaderPath = "shaders/vertex.glsl";
|
||||||
|
const std::string kTessellationCtrlPath = "shaders/tessellation_ctrl.glsl";
|
||||||
|
const std::string kTessellationEvalPath = "shaders/tessellation_eval.glsl";
|
||||||
const std::string kFragmentShaderPath = "shaders/fragment.glsl";
|
const std::string kFragmentShaderPath = "shaders/fragment.glsl";
|
||||||
|
|
||||||
const std::string kQuadVertexPath = "shaders/quad_vertex.glsl";
|
const std::string kQuadVertexPath = "shaders/quad_vertex.glsl";
|
||||||
|
@ -57,7 +59,9 @@ Scene::~Scene() {
|
||||||
void Scene::Init() {
|
void Scene::Init() {
|
||||||
glewInit();
|
glewInit();
|
||||||
|
|
||||||
glEnable(GL_DEPTH_TEST);
|
// GL_DEPTH_TEST causes artifacts in meshes made up of multiple triangles
|
||||||
|
// disabling for now
|
||||||
|
//glEnable(GL_DEPTH_TEST);
|
||||||
glEnable(GL_CULL_FACE);
|
glEnable(GL_CULL_FACE);
|
||||||
|
|
||||||
fbo_.Init(window_width, window_height);
|
fbo_.Init(window_width, window_height);
|
||||||
|
@ -74,21 +78,28 @@ void Scene::Init() {
|
||||||
|
|
||||||
// Currently creates a test triangle and initializes its buffers
|
// Currently creates a test triangle and initializes its buffers
|
||||||
void Scene::InitBuffers() {
|
void Scene::InitBuffers() {
|
||||||
GLuint vbo;
|
GLuint patch_vbo;
|
||||||
float vertices[] = {
|
// Quad vertices in 3D space
|
||||||
-0.5f, -0.5f, 0.0f,
|
float patchVertices[] = {
|
||||||
0.5f, -0.5f, 0.0f,
|
-0.5f, -0.5f, 0.0f, // Bottom-left
|
||||||
0.0f, 0.5f, 0.0f
|
0.5f, -0.5f, 0.0f, // Bottom-right
|
||||||
|
0.5f, 0.5f, 0.0f, // Top-right
|
||||||
|
-0.5f, 0.5f, 0.0f // Top-left
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
glGenBuffers(1, &vbo);
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, vbo);
|
|
||||||
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
|
|
||||||
|
|
||||||
glGenVertexArrays(1, &vao_);
|
glGenVertexArrays(1, &vao_);
|
||||||
|
glGenBuffers(1, &patch_vbo);
|
||||||
glBindVertexArray(vao_);
|
glBindVertexArray(vao_);
|
||||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
|
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, patch_vbo);
|
||||||
|
glBufferData(GL_ARRAY_BUFFER, sizeof(patchVertices), &patchVertices, GL_STATIC_DRAW);
|
||||||
|
|
||||||
|
// Position attribute
|
||||||
glEnableVertexAttribArray(0);
|
glEnableVertexAttribArray(0);
|
||||||
|
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
|
||||||
|
|
||||||
|
glBindVertexArray(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Scene::InitQuadBuffers() {
|
void Scene::InitQuadBuffers() {
|
||||||
|
@ -121,7 +132,7 @@ void Scene::InitQuadBuffers() {
|
||||||
|
|
||||||
// Allows for runtime shader updates
|
// Allows for runtime shader updates
|
||||||
void Scene::ReloadShader() {
|
void Scene::ReloadShader() {
|
||||||
GLuint new_shader = InitShader(kVertexShaderPath.c_str(), kFragmentShaderPath.c_str());
|
GLuint new_shader = InitShader(kVertexShaderPath.c_str(), kTessellationCtrlPath.c_str(), kTessellationEvalPath.c_str(), kFragmentShaderPath.c_str());
|
||||||
if (new_shader == -1) {
|
if (new_shader == -1) {
|
||||||
DEBUG_BREAK();
|
DEBUG_BREAK();
|
||||||
glClearColor(1.0f, 0.0f, 1.0f, 0.0f);
|
glClearColor(1.0f, 0.0f, 1.0f, 0.0f);
|
||||||
|
@ -141,6 +152,8 @@ void Scene::Display(GLFWwindow* window) {
|
||||||
|
|
||||||
glUseProgram(shader_program_);
|
glUseProgram(shader_program_);
|
||||||
|
|
||||||
|
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
||||||
|
|
||||||
view_matrix_ = glm::lookAt(glm::vec3(Uniforms::SceneData.eye_w), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 1.0f, 0.0f));
|
view_matrix_ = glm::lookAt(glm::vec3(Uniforms::SceneData.eye_w), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 1.0f, 0.0f));
|
||||||
Uniforms::SceneData.PV = projection_matrix_ * view_matrix_; // Projection-View matrix
|
Uniforms::SceneData.PV = projection_matrix_ * view_matrix_; // Projection-View matrix
|
||||||
Uniforms::BufferSceneData();
|
Uniforms::BufferSceneData();
|
||||||
|
@ -149,7 +162,10 @@ void Scene::Display(GLFWwindow* window) {
|
||||||
glUniformMatrix4fv(Uniforms::UniformLocs::M, 1, false, glm::value_ptr(model_matrix));
|
glUniformMatrix4fv(Uniforms::UniformLocs::M, 1, false, glm::value_ptr(model_matrix));
|
||||||
|
|
||||||
glBindVertexArray(vao_);
|
glBindVertexArray(vao_);
|
||||||
glDrawArrays(GL_TRIANGLES, 0, 3);
|
glPatchParameteri(GL_PATCH_VERTICES, 4);
|
||||||
|
glDrawArrays(GL_PATCHES, 0, 4);
|
||||||
|
|
||||||
|
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
||||||
|
|
||||||
fbo_.Unbind();
|
fbo_.Unbind();
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue