Conflicts: examples/CMakeLists.txtmaster
commit
d73505887d
4 changed files with 865 additions and 3 deletions
@ -0,0 +1,11 @@ |
||||
CMakeFiles |
||||
cmake_install.cmake |
||||
CMakeCache.txt |
||||
Makefile |
||||
cmake_uninstall.cmake |
||||
src/config.h |
||||
src/x11/libglfw.pc |
||||
src/win32/libglfw.pc |
||||
src/cocoa/libglfw.pc |
||||
*.so |
||||
*.a |
@ -0,0 +1,849 @@ |
||||
//========================================================================
|
||||
// Heightmap example program using OpenGL 3 core profile
|
||||
// Copyright (c) 2010 Olivier Delannoy
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
// arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it
|
||||
// freely, subject to the following restrictions:
|
||||
//
|
||||
// 1. The origin of this software must not be misrepresented; you must not
|
||||
// claim that you wrote the original software. If you use this software
|
||||
// in a product, an acknowledgment in the product documentation would
|
||||
// be appreciated but is not required.
|
||||
//
|
||||
// 2. Altered source versions must be plainly marked as such, and must not
|
||||
// be misrepresented as being the original software.
|
||||
//
|
||||
// 3. This notice may not be removed or altered from any source
|
||||
// distribution.
|
||||
//
|
||||
//========================================================================
|
||||
|
||||
#include <stdlib.h> |
||||
#include <stdio.h> |
||||
#include <math.h> |
||||
#include <assert.h> |
||||
#include <stddef.h> |
||||
#include "getopt.h" |
||||
|
||||
|
||||
#define GLFW_NO_GLU 1 |
||||
#include <GL/glfw3.h> |
||||
|
||||
/* OpenGL 3.3 support
|
||||
* Functions are effectively mapped in init_opengl() */ |
||||
#ifndef GL_VERSION_3_0 |
||||
/* no defines */ |
||||
#endif |
||||
|
||||
#ifndef GL_VERSION_2_0 |
||||
|
||||
typedef char GLchar; |
||||
|
||||
#define GL_BLEND_EQUATION_RGB 0x8009 |
||||
#define GL_VERTEX_ATTRIB_ARRAY_ENABLED 0x8622 |
||||
#define GL_VERTEX_ATTRIB_ARRAY_SIZE 0x8623 |
||||
#define GL_VERTEX_ATTRIB_ARRAY_STRIDE 0x8624 |
||||
#define GL_VERTEX_ATTRIB_ARRAY_TYPE 0x8625 |
||||
#define GL_CURRENT_VERTEX_ATTRIB 0x8626 |
||||
#define GL_VERTEX_PROGRAM_POINT_SIZE 0x8642 |
||||
#define GL_VERTEX_ATTRIB_ARRAY_POINTER 0x8645 |
||||
#define GL_STENCIL_BACK_FUNC 0x8800 |
||||
#define GL_STENCIL_BACK_FAIL 0x8801 |
||||
#define GL_STENCIL_BACK_PASS_DEPTH_FAIL 0x8802 |
||||
#define GL_STENCIL_BACK_PASS_DEPTH_PASS 0x8803 |
||||
#define GL_MAX_DRAW_BUFFERS 0x8824 |
||||
#define GL_DRAW_BUFFER0 0x8825 |
||||
#define GL_DRAW_BUFFER1 0x8826 |
||||
#define GL_DRAW_BUFFER2 0x8827 |
||||
#define GL_DRAW_BUFFER3 0x8828 |
||||
#define GL_DRAW_BUFFER4 0x8829 |
||||
#define GL_DRAW_BUFFER5 0x882A |
||||
#define GL_DRAW_BUFFER6 0x882B |
||||
#define GL_DRAW_BUFFER7 0x882C |
||||
#define GL_DRAW_BUFFER8 0x882D |
||||
#define GL_DRAW_BUFFER9 0x882E |
||||
#define GL_DRAW_BUFFER10 0x882F |
||||
#define GL_DRAW_BUFFER11 0x8830 |
||||
#define GL_DRAW_BUFFER12 0x8831 |
||||
#define GL_DRAW_BUFFER13 0x8832 |
||||
#define GL_DRAW_BUFFER14 0x8833 |
||||
#define GL_DRAW_BUFFER15 0x8834 |
||||
#define GL_BLEND_EQUATION_ALPHA 0x883D |
||||
#define GL_MAX_VERTEX_ATTRIBS 0x8869 |
||||
#define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED 0x886A |
||||
#define GL_MAX_TEXTURE_IMAGE_UNITS 0x8872 |
||||
#define GL_FRAGMENT_SHADER 0x8B30 |
||||
#define GL_VERTEX_SHADER 0x8B31 |
||||
#define GL_MAX_FRAGMENT_UNIFORM_COMPONENTS 0x8B49 |
||||
#define GL_MAX_VERTEX_UNIFORM_COMPONENTS 0x8B4A |
||||
#define GL_MAX_VARYING_FLOATS 0x8B4B |
||||
#define GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS 0x8B4C |
||||
#define GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS 0x8B4D |
||||
#define GL_SHADER_TYPE 0x8B4F |
||||
#define GL_FLOAT_VEC2 0x8B50 |
||||
#define GL_FLOAT_VEC3 0x8B51 |
||||
#define GL_FLOAT_VEC4 0x8B52 |
||||
#define GL_INT_VEC2 0x8B53 |
||||
#define GL_INT_VEC3 0x8B54 |
||||
#define GL_INT_VEC4 0x8B55 |
||||
#define GL_BOOL 0x8B56 |
||||
#define GL_BOOL_VEC2 0x8B57 |
||||
#define GL_BOOL_VEC3 0x8B58 |
||||
#define GL_BOOL_VEC4 0x8B59 |
||||
#define GL_FLOAT_MAT2 0x8B5A |
||||
#define GL_FLOAT_MAT3 0x8B5B |
||||
#define GL_FLOAT_MAT4 0x8B5C |
||||
#define GL_SAMPLER_1D 0x8B5D |
||||
#define GL_SAMPLER_2D 0x8B5E |
||||
#define GL_SAMPLER_3D 0x8B5F |
||||
#define GL_SAMPLER_CUBE 0x8B60 |
||||
#define GL_SAMPLER_1D_SHADOW 0x8B61 |
||||
#define GL_SAMPLER_2D_SHADOW 0x8B62 |
||||
#define GL_DELETE_STATUS 0x8B80 |
||||
#define GL_COMPILE_STATUS 0x8B81 |
||||
#define GL_LINK_STATUS 0x8B82 |
||||
#define GL_VALIDATE_STATUS 0x8B83 |
||||
#define GL_INFO_LOG_LENGTH 0x8B84 |
||||
#define GL_ATTACHED_SHADERS 0x8B85 |
||||
#define GL_ACTIVE_UNIFORMS 0x8B86 |
||||
#define GL_ACTIVE_UNIFORM_MAX_LENGTH 0x8B87 |
||||
#define GL_SHADER_SOURCE_LENGTH 0x8B88 |
||||
#define GL_ACTIVE_ATTRIBUTES 0x8B89 |
||||
#define GL_ACTIVE_ATTRIBUTE_MAX_LENGTH 0x8B8A |
||||
#define GL_FRAGMENT_SHADER_DERIVATIVE_HINT 0x8B8B |
||||
#define GL_SHADING_LANGUAGE_VERSION 0x8B8C |
||||
#define GL_CURRENT_PROGRAM 0x8B8D |
||||
#define GL_POINT_SPRITE_COORD_ORIGIN 0x8CA0 |
||||
#define GL_LOWER_LEFT 0x8CA1 |
||||
#define GL_UPPER_LEFT 0x8CA2 |
||||
#define GL_STENCIL_BACK_REF 0x8CA3 |
||||
#define GL_STENCIL_BACK_VALUE_MASK 0x8CA4 |
||||
#define GL_STENCIL_BACK_WRITEMASK 0x8CA5 |
||||
#endif |
||||
|
||||
|
||||
|
||||
#ifndef GL_VERSION_1_5 |
||||
|
||||
typedef ptrdiff_t GLintptr; |
||||
typedef ptrdiff_t GLsizeiptr; |
||||
|
||||
#define GL_BUFFER_SIZE 0x8764 |
||||
#define GL_BUFFER_USAGE 0x8765 |
||||
#define GL_QUERY_COUNTER_BITS 0x8864 |
||||
#define GL_CURRENT_QUERY 0x8865 |
||||
#define GL_QUERY_RESULT 0x8866 |
||||
#define GL_QUERY_RESULT_AVAILABLE 0x8867 |
||||
#define GL_ARRAY_BUFFER 0x8892 |
||||
#define GL_ELEMENT_ARRAY_BUFFER 0x8893 |
||||
#define GL_ARRAY_BUFFER_BINDING 0x8894 |
||||
#define GL_ELEMENT_ARRAY_BUFFER_BINDING 0x8895 |
||||
#define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING 0x889F |
||||
#define GL_READ_ONLY 0x88B8 |
||||
#define GL_WRITE_ONLY 0x88B9 |
||||
#define GL_READ_WRITE 0x88BA |
||||
#define GL_BUFFER_ACCESS 0x88BB |
||||
#define GL_BUFFER_MAPPED 0x88BC |
||||
#define GL_BUFFER_MAP_POINTER 0x88BD |
||||
#define GL_STREAM_DRAW 0x88E0 |
||||
#define GL_STREAM_READ 0x88E1 |
||||
#define GL_STREAM_COPY 0x88E2 |
||||
#define GL_STATIC_DRAW 0x88E4 |
||||
#define GL_STATIC_READ 0x88E5 |
||||
#define GL_STATIC_COPY 0x88E6 |
||||
#define GL_DYNAMIC_DRAW 0x88E8 |
||||
#define GL_DYNAMIC_READ 0x88E9 |
||||
#define GL_DYNAMIC_COPY 0x88EA |
||||
#define GL_SAMPLES_PASSED 0x8914 |
||||
#endif |
||||
|
||||
|
||||
|
||||
|
||||
/* OpenGL 3.0 */ |
||||
typedef void (APIENTRY * PFN_glGenVertexArrays)(GLsizei n, GLuint *arrays); |
||||
typedef void (APIENTRY * PFN_glBindVertexArray)(GLuint array); |
||||
typedef void (APIENTRY * PFN_glDeleteVertexArrays)(GLsizei n, GLuint *arrays); |
||||
/* OpenGL 2.0 */ |
||||
typedef GLuint (APIENTRY * PFN_glCreateShader)(GLenum type); |
||||
typedef void (APIENTRY * PFN_glDeleteShader)(GLuint shader); |
||||
typedef void (APIENTRY * PFN_glCompileShader)(GLuint shader); |
||||
typedef void (APIENTRY * PFN_glShaderSource)(GLuint shader, GLsizei count, const GLchar* *string, const GLint *length); |
||||
typedef void (APIENTRY * PFN_glGetShaderiv)(GLuint shader, GLenum pname, GLint *params); |
||||
typedef void (APIENTRY * PFN_glGetShaderInfoLog)(GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog); |
||||
typedef GLuint (APIENTRY * PFN_glCreateProgram)(void); |
||||
typedef void (APIENTRY * PFN_glDeleteProgram)(GLuint program); |
||||
typedef void (APIENTRY * PFN_glAttachShader)(GLuint program, GLuint shader); |
||||
typedef void (APIENTRY * PFN_glLinkProgram)(GLuint program); |
||||
typedef void (APIENTRY * PFN_glGetProgramiv)(GLuint program, GLenum pname, GLint *params); |
||||
typedef void (APIENTRY * PFN_glGetProgramInfoLog)(GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog); |
||||
typedef void (APIENTRY * PFN_glValidateProgram)(GLuint program); |
||||
typedef void (APIENTRY * PFN_glUseProgram)(GLuint program); |
||||
typedef GLint (APIENTRY * PFN_glGetUniformLocation)(GLuint program, const GLchar *name); |
||||
typedef void (APIENTRY * PFN_glUniformMatrix4fv)(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); |
||||
typedef GLint (APIENTRY * PFN_glGetAttribLocation)(GLuint program, const GLchar *name); |
||||
typedef void (APIENTRY * PFN_glEnableVertexAttribArray)(GLuint index); |
||||
typedef void (APIENTRY * PFN_glVertexAttrib1f)(GLuint index, GLfloat x); |
||||
typedef void (APIENTRY * PFN_glVertexAttribPointer)(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid *pointer); |
||||
/* OpenGL 1.5 */
|
||||
typedef void (APIENTRY * PFN_glBindBuffer)(GLenum target, GLuint buffer); |
||||
typedef void (APIENTRY * PFN_glDeleteBuffers)(GLsizei n, const GLuint *buffers); |
||||
typedef void (APIENTRY * PFN_glGenBuffers)(GLsizei n, GLuint *buffers); |
||||
typedef void (APIENTRY * PFN_glBufferData)(GLenum target, GLsizeiptr size, const GLvoid *data, GLenum usage); |
||||
typedef void (APIENTRY * PFN_glBufferSubData)(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid *data); |
||||
|
||||
/* OpenGL function pointers */
|
||||
static PFN_glGenBuffers pglGenBuffers = NULL; |
||||
static PFN_glGenVertexArrays pglGenVertexArrays = NULL; |
||||
static PFN_glDeleteVertexArrays pglDeleteVertexArrays = NULL; |
||||
static PFN_glCreateShader pglCreateShader = NULL; |
||||
static PFN_glShaderSource pglShaderSource = NULL; |
||||
static PFN_glCompileShader pglCompileShader = NULL; |
||||
static PFN_glGetShaderiv pglGetShaderiv = NULL; |
||||
static PFN_glGetShaderInfoLog pglGetShaderInfoLog = NULL; |
||||
static PFN_glDeleteShader pglDeleteShader = NULL; |
||||
static PFN_glCreateProgram pglCreateProgram = NULL; |
||||
static PFN_glAttachShader pglAttachShader = NULL; |
||||
static PFN_glLinkProgram pglLinkProgram = NULL; |
||||
static PFN_glUseProgram pglUseProgram = NULL; |
||||
static PFN_glGetProgramiv pglGetProgramiv = NULL; |
||||
static PFN_glGetProgramInfoLog pglGetProgramInfoLog = NULL; |
||||
static PFN_glDeleteProgram pglDeleteProgram = NULL; |
||||
static PFN_glGetUniformLocation pglGetUniformLocation = NULL; |
||||
static PFN_glUniformMatrix4fv pglUniformMatrix4fv = NULL; |
||||
static PFN_glGetAttribLocation pglGetAttribLocation = NULL; |
||||
|
||||
/* Map height updates */ |
||||
#define MAX_CIRCLE_SIZE (5.0f) |
||||
#define MAX_DISPLACEMENT (1.0f) |
||||
#define DISPLACEMENT_SIGN_LIMIT (0.3f) |
||||
#define MAX_ITER (200) |
||||
#define NUM_ITER_AT_A_TIME (1) |
||||
|
||||
/* Map general information */ |
||||
#define MAP_SIZE (10.0f) |
||||
#define MAP_NUM_VERTICES (80) |
||||
#define MAP_NUM_TOTAL_VERTICES (MAP_NUM_VERTICES*MAP_NUM_VERTICES) |
||||
#define MAP_NUM_LINES (3* (MAP_NUM_VERTICES - 1) * (MAP_NUM_VERTICES - 1) + \ |
||||
2 * (MAP_NUM_VERTICES - 1)) |
||||
|
||||
|
||||
/* OpenGL function pointers */ |
||||
|
||||
static PFN_glBindVertexArray pglBindVertexArray = NULL; |
||||
static PFN_glBufferData pglBufferData = NULL; |
||||
static PFN_glBindBuffer pglBindBuffer = NULL; |
||||
static PFN_glBufferSubData pglBufferSubData = NULL; |
||||
static PFN_glEnableVertexAttribArray pglEnableVertexAttribArray = NULL; |
||||
static PFN_glVertexAttribPointer pglVertexAttribPointer = NULL; |
||||
|
||||
#define RESOLVE_GL_FCN(type, var, name) \ |
||||
if (status == GL_TRUE) \
|
||||
{\
|
||||
var = glfwGetProcAddress((name));\
|
||||
if ((var) == NULL)\
|
||||
{\
|
||||
status = GL_FALSE;\
|
||||
}\
|
||||
} |
||||
|
||||
|
||||
static GLboolean init_opengl(void) |
||||
{ |
||||
GLboolean status = GL_TRUE; |
||||
RESOLVE_GL_FCN(PFN_glCreateShader, pglCreateShader, "glCreateShader"); |
||||
RESOLVE_GL_FCN(PFN_glShaderSource, pglShaderSource, "glShaderSource"); |
||||
RESOLVE_GL_FCN(PFN_glCompileShader, pglCompileShader, "glCompileShader"); |
||||
RESOLVE_GL_FCN(PFN_glGetShaderiv, pglGetShaderiv, "glGetShaderiv"); |
||||
RESOLVE_GL_FCN(PFN_glGetShaderInfoLog, pglGetShaderInfoLog, "glGetShaderInfoLog"); |
||||
RESOLVE_GL_FCN(PFN_glDeleteShader, pglDeleteShader, "glDeleteShader"); |
||||
RESOLVE_GL_FCN(PFN_glCreateProgram, pglCreateProgram, "glCreateProgram"); |
||||
RESOLVE_GL_FCN(PFN_glAttachShader, pglAttachShader, "glAttachShader"); |
||||
RESOLVE_GL_FCN(PFN_glLinkProgram, pglLinkProgram, "glLinkProgram"); |
||||
RESOLVE_GL_FCN(PFN_glUseProgram, pglUseProgram, "glUseProgram"); |
||||
RESOLVE_GL_FCN(PFN_glGetProgramiv, pglGetProgramiv, "glGetProgramiv"); |
||||
RESOLVE_GL_FCN(PFN_glGetProgramInfoLog, pglGetProgramInfoLog, "glGetProgramInfoLog"); |
||||
RESOLVE_GL_FCN(PFN_glDeleteProgram, pglDeleteProgram, "glDeleteProgram"); |
||||
RESOLVE_GL_FCN(PFN_glGetUniformLocation, pglGetUniformLocation, "glGetUniformLocation"); |
||||
RESOLVE_GL_FCN(PFN_glUniformMatrix4fv, pglUniformMatrix4fv, "glUniformMatrix4fv"); |
||||
RESOLVE_GL_FCN(PFN_glGetAttribLocation, pglGetAttribLocation, "glGetAttribLocation"); |
||||
RESOLVE_GL_FCN(PFN_glGenVertexArrays, pglGenVertexArrays, "glGenVertexArrays"); |
||||
RESOLVE_GL_FCN(PFN_glDeleteVertexArrays, pglDeleteVertexArrays, "glDeleteVertexArrays"); |
||||
RESOLVE_GL_FCN(PFN_glBindVertexArray, pglBindVertexArray, "glBindVertexArray"); |
||||
RESOLVE_GL_FCN(PFN_glGenBuffers, pglGenBuffers, "glGenBuffers"); |
||||
RESOLVE_GL_FCN(PFN_glBindBuffer, pglBindBuffer, "glBindBuffer"); |
||||
RESOLVE_GL_FCN(PFN_glBufferData, pglBufferData, "glBufferData"); |
||||
RESOLVE_GL_FCN(PFN_glBufferSubData, pglBufferSubData, "glBufferSubData"); |
||||
RESOLVE_GL_FCN(PFN_glEnableVertexAttribArray, pglEnableVertexAttribArray, "glEnableVertexAttribArray"); |
||||
RESOLVE_GL_FCN(PFN_glVertexAttribPointer, pglVertexAttribPointer, "glVertexAttribPointer"); |
||||
return status; |
||||
} |
||||
/**********************************************************************
|
||||
* Default shader programs |
||||
*********************************************************************/ |
||||
|
||||
static const char* default_vertex_shader = |
||||
"#version 150\n" |
||||
"uniform mat4 project;\n" |
||||
"uniform mat4 modelview;\n" |
||||
"in float x;\n" |
||||
"in float y;\n" |
||||
"in float z;\n" |
||||
"\n" |
||||
"void main()\n" |
||||
"{\n" |
||||
" gl_Position = project * modelview * vec4(x, y, z, 1.0);\n" |
||||
"}\n"; |
||||
|
||||
static const char* default_fragment_shader = |
||||
"#version 150\n" |
||||
"out vec4 gl_FragColor;\n" |
||||
"void main()\n" |
||||
"{\n" |
||||
" gl_FragColor = vec4(0.2, 1.0, 0.2, 1.0); \n" |
||||
"}\n"; |
||||
|
||||
/**********************************************************************
|
||||
* Values for shader uniforms |
||||
*********************************************************************/ |
||||
|
||||
/* Frustum configuration */ |
||||
static GLfloat view_angle = 45.0f; |
||||
static GLfloat aspect_ratio = 4.0f/3.0f; |
||||
static GLfloat z_near = 1.0f; |
||||
static GLfloat z_far = 100.f; |
||||
|
||||
/* Projection matrix */ |
||||
static GLfloat projection_matrix[16] = { |
||||
1.0f, 0.0f, 0.0f, 0.0f, |
||||
0.0f, 1.0f, 0.0f, 0.0f, |
||||
0.0f, 0.0f, 1.0f, 0.0f, |
||||
0.0f, 0.0f, 0.0f, 1.0f |
||||
}; |
||||
|
||||
/* Model view matrix */ |
||||
static GLfloat modelview_matrix[16] = { |
||||
1.0f, 0.0f, 0.0f, 0.0f, |
||||
0.0f, 1.0f, 0.0f, 0.0f, |
||||
0.0f, 0.0f, 1.0f, 0.0f, |
||||
0.0f, 0.0f, 0.0f, 1.0f |
||||
}; |
||||
|
||||
/**********************************************************************
|
||||
* Heightmap vertex and index data |
||||
*********************************************************************/ |
||||
|
||||
static GLfloat map_vertices[3][MAP_NUM_TOTAL_VERTICES]; |
||||
static GLuint map_line_indices[2*MAP_NUM_LINES]; |
||||
|
||||
/* Store uniform location for the shaders
|
||||
* Those values are setup as part of the process of creating |
||||
* the shader program. They should not be used before creating |
||||
* the program. |
||||
*/ |
||||
static GLuint mesh; |
||||
static GLuint mesh_vbo[4]; |
||||
|
||||
/**********************************************************************
|
||||
* OpenGL helper functions |
||||
*********************************************************************/ |
||||
|
||||
/* Load a (text) file into memory and return its contents
|
||||
*/ |
||||
static char* read_file_content(const char* filename) |
||||
{ |
||||
FILE* fd; |
||||
size_t size = 0; |
||||
char* result = NULL; |
||||
|
||||
fd = fopen(filename, "r"); |
||||
if (fd != NULL) |
||||
{ |
||||
size = fseek(fd, 0, SEEK_END); |
||||
(void) fseek(fd, 0, SEEK_SET); |
||||
|
||||
result = malloc(size + 1); |
||||
result[size] = '\0'; |
||||
if (fread(result, size, 1, fd) != 1) |
||||
{ |
||||
free(result); |
||||
result = NULL; |
||||
} |
||||
(void) fclose(fd); |
||||
} |
||||
return result; |
||||
} |
||||
|
||||
/* Creates a shader object of the specified type using the specified text
|
||||
*/ |
||||
static GLuint make_shader(GLenum type, const char* shader_src) |
||||
{ |
||||
GLuint shader; |
||||
GLint shader_ok; |
||||
GLsizei log_length; |
||||
char info_log[8192]; |
||||
|
||||
shader = pglCreateShader(type); |
||||
if (shader != 0) |
||||
{ |
||||
pglShaderSource(shader, 1, (const GLchar**)&shader_src, NULL); |
||||
pglCompileShader(shader); |
||||
pglGetShaderiv(shader, GL_COMPILE_STATUS, &shader_ok); |
||||
if (shader_ok != GL_TRUE) |
||||
{ |
||||
fprintf(stderr, "ERROR: Failed to compile %s shader\n", (type == GL_FRAGMENT_SHADER) ? "fragment" : "vertex" ); |
||||
pglGetShaderInfoLog(shader, 8192, &log_length,info_log); |
||||
fprintf(stderr, "ERROR: \n%s\n\n", info_log); |
||||
pglDeleteShader(shader); |
||||
shader = 0; |
||||
} |
||||
} |
||||
return shader; |
||||
} |
||||
|
||||
/* Creates a program object using the specified vertex and fragment text
|
||||
*/ |
||||
static GLuint make_shader_program(const char* vertex_shader_src, const char* fragment_shader_src) |
||||
{ |
||||
GLuint program = 0u; |
||||
GLint program_ok; |
||||
GLuint vertex_shader = 0u; |
||||
GLuint fragment_shader = 0u; |
||||
GLsizei log_length; |
||||
char info_log[8192]; |
||||
|
||||
vertex_shader = make_shader(GL_VERTEX_SHADER, (vertex_shader_src == NULL) ? default_vertex_shader : vertex_shader_src); |
||||
if (vertex_shader != 0u) |
||||
{ |
||||
fragment_shader = make_shader(GL_FRAGMENT_SHADER, (fragment_shader_src == NULL) ? default_fragment_shader : fragment_shader_src); |
||||
if (fragment_shader != 0u) |
||||
{ |
||||
/* make the program that connect the two shader and link it */ |
||||
program = pglCreateProgram(); |
||||
if (program != 0u) |
||||
{ |
||||
/* attach both shader and link */ |
||||
pglAttachShader(program, vertex_shader); |
||||
pglAttachShader(program, fragment_shader); |
||||
pglLinkProgram(program); |
||||
pglGetProgramiv(program, GL_LINK_STATUS, &program_ok); |
||||
|
||||
if (program_ok != GL_TRUE) |
||||
{ |
||||
fprintf(stderr, "ERROR, failed to link shader program\n"); |
||||
pglGetProgramInfoLog(program, 8192, &log_length, info_log); |
||||
fprintf(stderr, "ERROR: \n%s\n\n", info_log); |
||||
pglDeleteProgram(program); |
||||
pglDeleteShader(fragment_shader); |
||||
pglDeleteShader(vertex_shader); |
||||
program = 0u; |
||||
} |
||||
} |
||||
} |
||||
else |
||||
{ |
||||
fprintf(stderr, "ERROR: Unable to load fragment shader\n"); |
||||
pglDeleteShader(vertex_shader); |
||||
} |
||||
} |
||||
else |
||||
{ |
||||
fprintf(stderr, "ERROR: Unable to load vertex shader\n"); |
||||
} |
||||
return program; |
||||
} |
||||
|
||||
/**********************************************************************
|
||||
* Geometry creation functions |
||||
*********************************************************************/ |
||||
|
||||
/* Generate vertices and indices for the heightmap
|
||||
*/ |
||||
static void init_map(void) |
||||
{ |
||||
int i; |
||||
int j; |
||||
int k; |
||||
GLfloat step = MAP_SIZE / (MAP_NUM_VERTICES - 1); |
||||
GLfloat x = 0.0f; |
||||
GLfloat z = 0.0f; |
||||
/* Create a flat grid */ |
||||
k = 0; |
||||
for (i = 0 ; i < MAP_NUM_VERTICES ; ++i) |
||||
{ |
||||
for (j = 0 ; j < MAP_NUM_VERTICES ; ++j) |
||||
{ |
||||
map_vertices[0][k] = x; |
||||
map_vertices[1][k] = 0.0f; |
||||
map_vertices[2][k] = z; |
||||
z += step; |
||||
++k; |
||||
} |
||||
x += step; |
||||
z = 0.0f; |
||||
} |
||||
#if DEBUG_ENABLED |
||||
for (i = 0 ; i < MAP_NUM_TOTAL_VERTICES ; ++i) |
||||
{ |
||||
printf ("Vertice %d (%f, %f, %f)\n", |
||||
i, map_vertices[0][i], map_vertices[1][i], map_vertices[2][i]); |
||||
|
||||
} |
||||
#endif |
||||
/* create indices */ |
||||
/* line fan based on i
|
||||
* i+1 |
||||
* | / i + n + 1 |
||||
* | / |
||||
* |/ |
||||
* i --- i + n |
||||
*/ |
||||
|
||||
/* close the top of the square */ |
||||
k = 0; |
||||
for (i = 0 ; i < MAP_NUM_VERTICES -1 ; ++i) |
||||
{ |
||||
map_line_indices[k++] = (i + 1) * MAP_NUM_VERTICES -1; |
||||
map_line_indices[k++] = (i + 2) * MAP_NUM_VERTICES -1; |
||||
} |
||||
/* close the right of the square */ |
||||
for (i = 0 ; i < MAP_NUM_VERTICES -1 ; ++i) |
||||
{ |
||||
map_line_indices[k++] = (MAP_NUM_VERTICES - 1) * MAP_NUM_VERTICES + i; |
||||
map_line_indices[k++] = (MAP_NUM_VERTICES - 1) * MAP_NUM_VERTICES + i + 1; |
||||
} |
||||
|
||||
for (i = 0 ; i < (MAP_NUM_VERTICES - 1) ; ++i) |
||||
{ |
||||
for (j = 0 ; j < (MAP_NUM_VERTICES - 1) ; ++j) |
||||
{ |
||||
int ref = i * (MAP_NUM_VERTICES) + j; |
||||
map_line_indices[k++] = ref; |
||||
map_line_indices[k++] = ref + 1; |
||||
|
||||
map_line_indices[k++] = ref; |
||||
map_line_indices[k++] = ref + MAP_NUM_VERTICES; |
||||
|
||||
map_line_indices[k++] = ref; |
||||
map_line_indices[k++] = ref + MAP_NUM_VERTICES + 1; |
||||
} |
||||
} |
||||
|
||||
#ifdef DEBUG_ENABLED |
||||
for (k = 0 ; k < 2 * MAP_NUM_LINES ; k += 2) |
||||
{ |
||||
int beg, end; |
||||
beg = map_line_indices[k]; |
||||
end = map_line_indices[k+1]; |
||||
printf ("Line %d: %d -> %d (%f, %f, %f) -> (%f, %f, %f)\n", |
||||
k / 2, beg, end, |
||||
map_vertices[0][beg], map_vertices[1][beg], map_vertices[2][beg], |
||||
map_vertices[0][end], map_vertices[1][end], map_vertices[2][end]); |
||||
} |
||||
#endif |
||||
} |
||||
|
||||
static void generate_heightmap__circle(float* center_x, float* center_y, |
||||
float* size, float* displacement) |
||||
{ |
||||
float sign; |
||||
/* random value for element in between [0-1.0] */ |
||||
*center_x = (MAP_SIZE * rand()) / (1.0f * RAND_MAX); |
||||
*center_y = (MAP_SIZE * rand()) / (1.0f * RAND_MAX); |
||||
*size = (MAX_CIRCLE_SIZE * rand()) / (1.0f * RAND_MAX); |
||||
sign = (1.0f * rand()) / (1.0f * RAND_MAX); |
||||
sign = (sign < DISPLACEMENT_SIGN_LIMIT) ? -1.0f : 1.0f; |
||||
*displacement = (sign * (MAX_DISPLACEMENT * rand())) / (1.0f * RAND_MAX); |
||||
} |
||||
|
||||
/* Run the specified number of iterations of the generation process for the
|
||||
* heightmap |
||||
*/ |
||||
static void update_map(int num_iter) |
||||
{ |
||||
assert(num_iter > 0); |
||||
while(num_iter) |
||||
{ |
||||
/* center of the circle */ |
||||
float center_x; |
||||
float center_z; |
||||
float circle_size; |
||||
float disp; |
||||
size_t ii; |
||||
generate_heightmap__circle(¢er_x, ¢er_z, &circle_size, &disp); |
||||
disp = disp / 2.0f; |
||||
for (ii = 0u ; ii < MAP_NUM_TOTAL_VERTICES ; ++ii) |
||||
{ |
||||
GLfloat dx = center_x - map_vertices[0][ii]; |
||||
GLfloat dz = center_z - map_vertices[2][ii]; |
||||
GLfloat pd = (2.0f * sqrtf((dx * dx) + (dz * dz))) / circle_size; |
||||
if (fabs(pd) <= 1.0f) |
||||
{ |
||||
/* tx,tz is within the circle */ |
||||
GLfloat new_height = disp + (cos(pd*3.14f)*disp); |
||||
map_vertices[1][ii] += new_height; |
||||
} |
||||
} |
||||
--num_iter; |
||||
} |
||||
} |
||||
|
||||
/**********************************************************************
|
||||
* OpenGL helper functions |
||||
*********************************************************************/ |
||||
|
||||
/* Create VBO, IBO and VAO objects for the heightmap geometry and bind them to
|
||||
* the specified program object |
||||
*/ |
||||
static void make_mesh(GLuint program) |
||||
{ |
||||
GLuint attrloc; |
||||
|
||||
pglGenVertexArrays(1, &mesh); |
||||
pglGenBuffers(4, mesh_vbo); |
||||
pglBindVertexArray(mesh); |
||||
/* Prepare the data for drawing through a buffer inidices */ |
||||
pglBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh_vbo[3]); |
||||
pglBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLuint)* MAP_NUM_LINES * 2, map_line_indices, GL_STATIC_DRAW); |
||||
|
||||
/* Prepare the attributes for rendering */ |
||||
attrloc = pglGetAttribLocation(program, "x"); |
||||
pglBindBuffer(GL_ARRAY_BUFFER, mesh_vbo[0]); |
||||
pglBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * MAP_NUM_TOTAL_VERTICES, &map_vertices[0][0], GL_STATIC_DRAW); |
||||
pglEnableVertexAttribArray(attrloc); |
||||
pglVertexAttribPointer(attrloc, 1, GL_FLOAT, GL_FALSE, 0, 0); |
||||
|
||||
attrloc = pglGetAttribLocation(program, "z"); |
||||
pglBindBuffer(GL_ARRAY_BUFFER, mesh_vbo[2]); |
||||
pglBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * MAP_NUM_TOTAL_VERTICES, &map_vertices[2][0], GL_STATIC_DRAW); |
||||
pglEnableVertexAttribArray(attrloc); |
||||
pglVertexAttribPointer(attrloc, 1, GL_FLOAT, GL_FALSE, 0, 0); |
||||
|
||||
attrloc = pglGetAttribLocation(program, "y"); |
||||
pglBindBuffer(GL_ARRAY_BUFFER, mesh_vbo[1]); |
||||
pglBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * MAP_NUM_TOTAL_VERTICES, &map_vertices[1][0], GL_DYNAMIC_DRAW); |
||||
pglEnableVertexAttribArray(attrloc); |
||||
pglVertexAttribPointer(attrloc, 1, GL_FLOAT, GL_FALSE, 0, 0); |
||||
} |
||||
|
||||
/* Update VBO vertices from source data
|
||||
*/ |
||||
static void update_mesh(void) |
||||
{ |
||||
pglBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(GLfloat) * MAP_NUM_TOTAL_VERTICES, &map_vertices[1][0]); |
||||
} |
||||
|
||||
/**********************************************************************
|
||||
* GLFW callback functions |
||||
*********************************************************************/ |
||||
|
||||
/* The program runs as long as this is GL_TRUE
|
||||
*/ |
||||
static GLboolean running = GL_TRUE; |
||||
|
||||
/* GLFW Window management functions */ |
||||
static int window_close_callback(GLFWwindow window) |
||||
{ |
||||
running = GL_FALSE; |
||||
|
||||
/* Disallow window closing
|
||||
* The window will be closed when the main loop terminates */ |
||||
return 0; |
||||
} |
||||
|
||||
static void key_callback(GLFWwindow window, int key, int action) |
||||
{ |
||||
switch(key) |
||||
{ |
||||
case GLFW_KEY_ESC: |
||||
/* Exit program on Escape */ |
||||
running = GL_FALSE; |
||||
break; |
||||
} |
||||
} |
||||
|
||||
/* Print usage information */ |
||||
static void usage(void) |
||||
{ |
||||
printf("Usage: heightmap [-v <vertex_shader_path>] [-f <fragment_shader_path>]\n"); |
||||
printf(" heightmap [-h]\n"); |
||||
} |
||||
|
||||
int main(int argc, char** argv) |
||||
{ |
||||
GLFWwindow window; |
||||
int ch, iter; |
||||
double dt; |
||||
double last_update_time; |
||||
int frame; |
||||
float f; |
||||
GLint uloc_modelview; |
||||
GLint uloc_project; |
||||
|
||||
char* vertex_shader_path = NULL; |
||||
char* fragment_shader_path = NULL; |
||||
char* vertex_shader_src = NULL; |
||||
char* fragment_shader_src = NULL; |
||||
GLuint shader_program; |
||||
|
||||
while ((ch = getopt(argc, argv, "f:v:h")) != -1) |
||||
{ |
||||
switch (ch) |
||||
{ |
||||
case 'f': |
||||
fragment_shader_path = optarg; |
||||
break; |
||||
case 'v': |
||||
vertex_shader_path = optarg; |
||||
break; |
||||
case 'h': |
||||
usage(); |
||||
exit(EXIT_SUCCESS); |
||||
default: |
||||
usage(); |
||||
exit(EXIT_FAILURE); |
||||
} |
||||
} |
||||
|
||||
if (fragment_shader_path) |
||||
{ |
||||
vertex_shader_src = read_file_content(fragment_shader_path); |
||||
if (!fragment_shader_src) |
||||
{ |
||||
fprintf(stderr, |
||||
"ERROR: unable to load fragment shader from '%s'\n", |
||||
fragment_shader_path); |
||||
exit(EXIT_FAILURE); |
||||
} |
||||
} |
||||
|
||||
if (vertex_shader_path) |
||||
{ |
||||
vertex_shader_src = read_file_content(vertex_shader_path); |
||||
if (!vertex_shader_src) |
||||
{ |
||||
fprintf(stderr, |
||||
"ERROR: unable to load vertex shader from '%s'\n", |
||||
fragment_shader_path); |
||||
exit(EXIT_FAILURE); |
||||
} |
||||
} |
||||
|
||||
if (GL_TRUE != glfwInit()) |
||||
{ |
||||
fprintf(stderr, "ERROR: Unable to initialize GLFW\n"); |
||||
usage(); |
||||
|
||||
free(vertex_shader_src); |
||||
free(fragment_shader_src); |
||||
exit(EXIT_FAILURE); |
||||
} |
||||
|
||||
glfwOpenWindowHint(GLFW_WINDOW_NO_RESIZE, GL_TRUE); |
||||
glfwOpenWindowHint(GLFW_OPENGL_VERSION_MAJOR, 3); |
||||
glfwOpenWindowHint(GLFW_OPENGL_VERSION_MINOR, 2); |
||||
glfwOpenWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); |
||||
glfwOpenWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_FALSE); |
||||
|
||||
window = glfwOpenWindow(800, 600, GLFW_WINDOWED, "GLFW OpenGL3 Heightmap demo"); |
||||
if (! window ) |
||||
{ |
||||
fprintf(stderr, "ERROR: Unable to create the OpenGL context and associated window\n"); |
||||
usage(); |
||||
|
||||
free(vertex_shader_src); |
||||
free(fragment_shader_src); |
||||
exit(EXIT_FAILURE); |
||||
} |
||||
glfwSetWindowCloseCallback(window, window_close_callback); |
||||
glfwSetKeyCallback(window, key_callback); |
||||
/* Register events callback */ |
||||
|
||||
if (GL_TRUE != init_opengl()) |
||||
{ |
||||
fprintf(stderr, "ERROR: unable to resolve OpenGL function pointers\n"); |
||||
free(vertex_shader_src); |
||||
free(fragment_shader_src); |
||||
exit(EXIT_FAILURE); |
||||
} |
||||
/* Prepare opengl resources for rendering */ |
||||
shader_program = make_shader_program(vertex_shader_src , fragment_shader_src); |
||||
free(vertex_shader_src); |
||||
free(fragment_shader_src); |
||||
|
||||
if (shader_program == 0u) |
||||
{ |
||||
fprintf(stderr, "ERROR: during creation of the shader program\n"); |
||||
usage(); |
||||
exit(EXIT_FAILURE); |
||||
} |
||||
|
||||
pglUseProgram(shader_program); |
||||
uloc_project = pglGetUniformLocation(shader_program, "project"); |
||||
uloc_modelview = pglGetUniformLocation(shader_program, "modelview"); |
||||
|
||||
/* Compute the projection matrix */ |
||||
f = 1.0f / tanf(view_angle / 2.0f); |
||||
projection_matrix[0] = f / aspect_ratio; |
||||
projection_matrix[5] = f; |
||||
projection_matrix[10] = (z_far + z_near)/ (z_near - z_far); |
||||
projection_matrix[11] = -1.0f; |
||||
projection_matrix[14] = 2.0f * (z_far * z_near) / (z_near - z_far); |
||||
pglUniformMatrix4fv(uloc_project, 1, GL_FALSE, projection_matrix); |
||||
|
||||
/* Set the camera position */ |
||||
modelview_matrix[12] = -5.0f; |
||||
modelview_matrix[13] = -5.0f; |
||||
modelview_matrix[14] = -20.0f; |
||||
pglUniformMatrix4fv(uloc_modelview, 1, GL_FALSE, modelview_matrix); |
||||
|
||||
/* Create mesh data */ |
||||
init_map(); |
||||
make_mesh(shader_program); |
||||
|
||||
/* Create vao + vbo to store the mesh */ |
||||
/* Create the vbo to store all the information for the grid and the height */ |
||||
|
||||
/* setup the scene ready for rendering */ |
||||
glViewport(0, 0, 800, 600); |
||||
glClearColor(0.0f, 0.0f, 0.0f, 0.0f); |
||||
|
||||
/* main loop */ |
||||
frame = 0; |
||||
iter = 0; |
||||
dt = last_update_time = glfwGetTime(); |
||||
|
||||
while (running) |
||||
{ |
||||
++frame; |
||||
/* render the next frame */ |
||||
glClear(GL_COLOR_BUFFER_BIT); |
||||
glDrawElements(GL_LINES, 2* MAP_NUM_LINES , GL_UNSIGNED_INT, 0); |
||||
|
||||
/* display and process events through callbacks */ |
||||
glfwSwapBuffers(); |
||||
glfwPollEvents(); |
||||
/* Check the frame rate and update the heightmap if needed */ |
||||
dt = glfwGetTime(); |
||||
if ((dt - last_update_time) > 0.2) |
||||
{ |
||||
/* generate the next iteration of the heightmap */ |
||||
if (iter < MAX_ITER) |
||||
{ |
||||
update_map(NUM_ITER_AT_A_TIME); |
||||
update_mesh(); |
||||
iter += NUM_ITER_AT_A_TIME; |
||||
} |
||||
last_update_time = dt; |
||||
frame = 0; |
||||
} |
||||
} |
||||
|
||||
exit(EXIT_SUCCESS); |
||||
} |
||||
|
Loading…
Reference in New Issue