Skip to content

Instantly share code, notes, and snippets.

@bananu7
Created March 21, 2014 16:40
Show Gist options
  • Save bananu7/9690357 to your computer and use it in GitHub Desktop.
Save bananu7/9690357 to your computer and use it in GitHub Desktop.
My Little Tesselation
#include <glload/gl_4_0.hpp>
#include <glload/gl_load.hpp>
#include <GLFW/glfw3.h>
#include <string>
#include <vector>
#include <iostream>
#define NL "\n"
bool compileSuccessful(unsigned obj) {
int status;
gl::GetShaderiv(obj, gl::COMPILE_STATUS, &status);
return status == gl::TRUE_;
}
bool linkSuccessful(unsigned program) {
int status;
gl::GetProgramiv(program, gl::LINK_STATUS, &status);
return status == gl::TRUE_;
}
std::string getShaderLog(unsigned shader)
{
GLsizei len;
char log[2048];
gl::GetShaderInfoLog(shader, sizeof(log), &len, log);
return log;
}
unsigned loadProgram () {
using std::string;
const string vss =
"#version 400 core"NL
"layout(location = 0) in vec2 position;"NL
"out vec2 vPosition;"NL
"void main() {"NL
" vPosition = position;"NL
" gl_Position = vec4(position, 0.0, 1.0);"NL
"}"NL
NL;
const string tcss =
"#version 400 core"NL
"layout(vertices = 4) out;"NL
"in vec2 vPosition[];"NL
"out vec2 tcPosition[];"NL
//"uniform float TessLevelInner;"NL
//"uniform float TessLevelOuter;"NL
"const float TessLevelInner = 16.0;"NL
"const float TessLevelOuter = 16.0;"NL
"#define ID gl_InvocationID"NL
"void main()"NL
"{"NL
" tcPosition[ID] = vPosition[ID];"NL
" if (ID == 0) {"NL
" gl_TessLevelInner[0] = TessLevelInner;"NL
" gl_TessLevelInner[1] = TessLevelInner;"NL
" gl_TessLevelOuter[0] = TessLevelOuter;"NL
" gl_TessLevelOuter[1] = TessLevelOuter;"NL
" gl_TessLevelOuter[2] = TessLevelOuter;"NL
" gl_TessLevelOuter[3] = TessLevelOuter;"NL
" }"NL
"}"NL
NL;
const string tess =
"#version 400 core"NL
"layout(quads) in;"NL
"in vec2 tcPosition[];"NL
"out vec2 tePosition;"NL
"#define ID gl_PrimitiveID"NL
"void main() {"NL
//"vec2 p0 = gl_TessCoord.x * tcPosition[0];"NL
//"vec2 p1 = gl_TessCoord.y * tcPosition[1];"NL
//"vec3 p2 = gl_TessCoord.z * tcPosition[2];"NL
//"vec2 tePosition = p0 + p1;"NL
"float u = gl_TessCoord.x, v = gl_TessCoord.y;"NL
"vec2 a = mix(tcPosition[0], tcPosition[1], u);"NL
"vec2 b = mix(tcPosition[2], tcPosition[3], u);"NL
//"vec2 a = mix(gl_in[0].gl_Position.xy, gl_in[1].gl_Position.xy, u);"NL
//"vec2 b = mix(gl_in[2].gl_Position.xy, gl_in[3].gl_Position.xy, u);"NL
"tePosition = mix(a, b, v);"NL
"tePosition.y += sin(u * 3.1416 * 2) * 0.1;"
//"vec2 tePosition = tcPosition[ID];"NL
" gl_Position = vec4(tePosition, 0.0, 1.0);"NL
"}"NL
NL;
const string fss =
"#version 400 core"NL
"out vec4 color;"NL
"in vec2 tePosition;"NL
"void main() {"NL
" color = vec4((tePosition + 1.0) * 0.5, 0.0, 1.0);"NL
"}"NL
NL;
auto vs = gl::CreateShader(gl::VERTEX_SHADER);
auto fs = gl::CreateShader(gl::FRAGMENT_SHADER);
auto tcs = gl::CreateShader(gl::TESS_CONTROL_SHADER);
auto tes = gl::CreateShader(gl::TESS_EVALUATION_SHADER);
auto shaderSource = [](unsigned shader, string const& source) {
auto const ptr = source.data();
int size = source.size();
gl::ShaderSource(shader, 1, &ptr, &size);
};
shaderSource(vs, vss);
shaderSource(fs, fss);
shaderSource(tcs, tcss);
shaderSource(tes, tess);
gl::CompileShader(vs);
gl::CompileShader(fs);
gl::CompileShader(tcs);
gl::CompileShader(tes);
std::cerr << "TCS: " << getShaderLog(tcs);
std::cerr << "TES: " << getShaderLog(tes);
unsigned program = gl::CreateProgram();
gl::AttachShader(program, vs);
gl::AttachShader(program, fs);
gl::AttachShader(program, tcs);
gl::AttachShader(program, tes);
gl::LinkProgram(program);
if (!linkSuccessful(program))
std::cerr << "LINK FAILED!\n";
gl::DeleteShader(vs);
gl::DeleteShader(fs);
gl::DeleteShader(tcs);
gl::DeleteShader(tes);
return program;
}
struct Mesh { unsigned vbo, vao; };
Mesh loadMesh() {
Mesh m;
gl::GenVertexArrays(1, &m.vao);
gl::GenBuffers(1, &m.vbo);
gl::BindVertexArray(m.vao);
float verts[] = {
-0.5f, -0.5f,
0.5f, -0.5f,
-0.5f, 0.5f,
0.5f, 0.5f
};
gl::BindBuffer(gl::ARRAY_BUFFER, m.vbo);
gl::BufferData(gl::ARRAY_BUFFER, sizeof(verts), verts, gl::STATIC_DRAW);
gl::EnableVertexAttribArray (0);
gl::VertexAttribPointer(0, 2, gl::FLOAT, gl::FALSE_, 0, 0);
return m;
}
int main(void) {
GLFWwindow* window;
/* Initialize the library */
if (!glfwInit())
return -1;
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, gl::TRUE_);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, gl::TRUE_);
glfwWindowHint(GLFW_OPENGL_CORE_PROFILE, GLFW_OPENGL_CORE_PROFILE);
/* Create a windowed mode window and its OpenGL context */
window = glfwCreateWindow(640, 480, "Hello World", NULL, NULL);
if (!window) {
glfwTerminate();
return -1;
}
/* Make the window's context current */
glfwMakeContextCurrent(window);
glload::LoadFunctions();
auto program = loadProgram();
auto mesh = loadMesh();
gl::BindVertexArray(mesh.vao);
/* Loop until the user closes the window */
while (!glfwWindowShouldClose(window)) {
/* Render here */
gl::UseProgram(program);
gl::PolygonMode(gl::FRONT_AND_BACK, gl::LINE);
gl::PatchParameteri(gl::PATCH_VERTICES, 4); // tell OpenGL that every patch has 16 verts
gl::DrawArrays(gl::PATCHES, 0, 4);
//gl::DrawArrays(gl::TRIANGLE_STRIP, 0, 4);
/* Swap front and back buffers */
glfwSwapBuffers(window);
/* Poll for and process events */
glfwPollEvents();
}
glfwTerminate();
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment