diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 69e7e2bc..69837dc0 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -22,8 +22,18 @@ # language governing permissions and limitations under the Apache License. # + + if( OPENGL_FOUND AND (GLEW_FOUND AND GLFW_FOUND) OR (APPLE AND GLFW_FOUND)) + # optional dependency - enables screenshots in some examples + find_package(PNG) + if (PNG_FOUND) + include_directories("${PNG_INCLUDE_DIRS}") + list(APPEND PLATFORM_LIBRARIES "${PNG_LIBRARIES}") + add_definitions(-DOPENSUBDIV_HAS_PNG) + endif() + add_subdirectory(common) add_subdirectory(glViewer) diff --git a/examples/common/CMakeLists.txt b/examples/common/CMakeLists.txt index 05c7aab2..47146e09 100644 --- a/examples/common/CMakeLists.txt +++ b/examples/common/CMakeLists.txt @@ -22,6 +22,11 @@ # language governing permissions and limitations under the Apache License. # +set(EXAMPLES_COMMON_SHADER_FILES + framebuffer.glsl + ssao.glsl +) + set(EXAMPLES_COMMON_SOURCE_FILES font_image.cpp hdr_reader.cpp @@ -43,10 +48,14 @@ set(EXAMPLES_COMMON_HEADER_FILES if( OPENGL_FOUND AND (GLEW_FOUND AND GLFW_FOUND) OR (APPLE AND GLFW_FOUND)) list(APPEND EXAMPLES_COMMON_SOURCE_FILES + gl_common.cpp + gl_framebuffer.cpp gl_hud.cpp ) list(APPEND EXAMPLES_COMMON_HEADER_FILES + gl_common.h + gl_framebuffer.h gl_hud.h ) @@ -81,10 +90,20 @@ endif() include_directories( "${PROJECT_SOURCE_DIR}/opensubdiv" + "${CMAKE_CURRENT_BINARY_DIR}" ) +set(INC_FILES ) + +_stringify("${EXAMPLES_COMMON_SHADER_FILES}" INC_FILES) + +source_group("Shaders" FILES ${EXAMPLES_COMMON_SHADER_FILES}) +source_group("Inc" FILES ${INC_FILES}) + add_library(examples_common_obj OBJECT ${EXAMPLES_COMMON_SOURCE_FILES} ${EXAMPLES_COMMON_HEADER_FILES} + ${INC_FILES} ) + diff --git a/examples/common/framebuffer.glsl b/examples/common/framebuffer.glsl new file mode 100644 index 00000000..e2b628d1 --- /dev/null +++ b/examples/common/framebuffer.glsl @@ -0,0 +1,66 @@ +// +// Copyright 2013 Pixar +// +// Licensed under the Apache License, Version 2.0 (the "Apache License") +// with the following modification; you may not use this file except in +// compliance with the Apache License and the following modification to it: +// Section 6. Trademarks. is deleted and replaced with: +// +// 6. Trademarks. This License does not grant permission to use the trade +// names, trademarks, service marks, or product names of the Licensor +// and its affiliates, except as required to comply with Section 4(c) of +// the License and to reproduce the content of the NOTICE file. +// +// You may obtain a copy of the Apache License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the Apache License with the above modification is +// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the Apache License for the specific +// language governing permissions and limitations under the Apache License. +// + +#version 410 + +//-------------------------------------------------------------- +// image vertex shader +//-------------------------------------------------------------- + +#ifdef IMAGE_VERTEX_SHADER + +layout (location=0) in vec2 position; +out vec2 outUV; + +void +main() +{ + outUV = vec2(position.xy*0.5) + vec2(0.5); + gl_Position = vec4(position.x, position.y, 0, 1); +} + +#endif + +//-------------------------------------------------------------- +#ifdef IMAGE_FRAGMENT_SHADER + +uniform sampler2D colorMap; +uniform sampler2D normalMap; +uniform sampler2D depthMap; + +in vec2 outUV; +out vec4 outColor; + +void main() +{ + + vec4 colorSample = texture(colorMap, outUV); + + //background color as a vertical grey ramp + vec4 bgColor = vec4(mix(0.05, 0.25, outUV.y)); + + outColor = mix(bgColor, colorSample, colorSample.a); +} + +#endif diff --git a/examples/common/gl_common.cpp b/examples/common/gl_common.cpp new file mode 100644 index 00000000..c266742c --- /dev/null +++ b/examples/common/gl_common.cpp @@ -0,0 +1,57 @@ +// +// Copyright 2013 Pixar +// +// Licensed under the Apache License, Version 2.0 (the "Apache License") +// with the following modification; you may not use this file except in +// compliance with the Apache License and the following modification to it: +// Section 6. Trademarks. is deleted and replaced with: +// +// 6. Trademarks. This License does not grant permission to use the trade +// names, trademarks, service marks, or product names of the Licensor +// and its affiliates, except as required to comply with Section 4(c) of +// the License and to reproduce the content of the NOTICE file. +// +// You may obtain a copy of the Apache License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the Apache License with the above modification is +// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the Apache License for the specific +// language governing permissions and limitations under the Apache License. +// + +#include "gl_common.h" + +void +checkGLErrors(std::string const & where) { + + GLuint err; + while ((err = glGetError()) != GL_NO_ERROR) { + std::cerr << "GL error: " + << (where.empty() ? "" : where + " ") + << err << "\n"; + } +} + +GLuint +compileShader(GLenum shaderType, const char *source) { + + GLuint shader = glCreateShader(shaderType); + glShaderSource(shader, 1, &source, NULL); + glCompileShader(shader); + + GLint status; + glGetShaderiv(shader, GL_COMPILE_STATUS, &status); + if (status == GL_FALSE) { + GLchar emsg[40960]; + glGetShaderInfoLog(shader, sizeof(emsg), 0, emsg); + fprintf(stderr, "Error compiling GLSL shader: %s\n", emsg); + return 0; + } + + return shader; +} + + diff --git a/examples/common/gl_common.h b/examples/common/gl_common.h new file mode 100644 index 00000000..3fc3dfea --- /dev/null +++ b/examples/common/gl_common.h @@ -0,0 +1,38 @@ +// +// Copyright 2013 Pixar +// +// Licensed under the Apache License, Version 2.0 (the "Apache License") +// with the following modification; you may not use this file except in +// compliance with the Apache License and the following modification to it: +// Section 6. Trademarks. is deleted and replaced with: +// +// 6. Trademarks. This License does not grant permission to use the trade +// names, trademarks, service marks, or product names of the Licensor +// and its affiliates, except as required to comply with Section 4(c) of +// the License and to reproduce the content of the NOTICE file. +// +// You may obtain a copy of the Apache License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the Apache License with the above modification is +// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the Apache License for the specific +// language governing permissions and limitations under the Apache License. +// + +#ifndef GL_COMMON_H +#define GL_COMMON_H + +#include + +#include +#include +#include + +void checkGLErrors(std::string const & where = ""); + +GLuint compileShader(GLenum shaderType, const char *source); + +#endif // GL_FRAMEBUFFER_H diff --git a/examples/common/gl_framebuffer.cpp b/examples/common/gl_framebuffer.cpp new file mode 100644 index 00000000..4f1fcf33 --- /dev/null +++ b/examples/common/gl_framebuffer.cpp @@ -0,0 +1,476 @@ +// +// Copyright 2013 Pixar +// +// Licensed under the Apache License, Version 2.0 (the "Apache License") +// with the following modification; you may not use this file except in +// compliance with the Apache License and the following modification to it: +// Section 6. Trademarks. is deleted and replaced with: +// +// 6. Trademarks. This License does not grant permission to use the trade +// names, trademarks, service marks, or product names of the Licensor +// and its affiliates, except as required to comply with Section 4(c) of +// the License and to reproduce the content of the NOTICE file. +// +// You may obtain a copy of the Apache License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the Apache License with the above modification is +// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the Apache License for the specific +// language governing permissions and limitations under the Apache License. +// + +#include "gl_framebuffer.h" +#include "gl_common.h" +#include "gl_hud.h" + +#include +#include +#include + +#ifdef OPENSUBDIV_HAS_PNG + #include + #include +#endif + + +GLFrameBuffer::GLFrameBuffer() : +_width(0), _height(0), +_frameBuffer(0), +_frameBufferColor(0), +_frameBufferNormal(0), +_frameBufferDepthTexture(0), +_program(0), +_vao(0), +_vbo(0) { +} + +GLFrameBuffer::~GLFrameBuffer() { + + glDeleteFramebuffers(1, &_frameBuffer); + glDeleteTextures(1, &_frameBufferColor); + glDeleteTextures(1, &_frameBufferNormal); + glDeleteTextures(1, &_frameBufferDepthTexture); + + glDeleteProgram(_program); + + glDeleteVertexArrays(1, &_vao); + glDeleteBuffers(1, &_vbo); +} + +static const char *g_framebufferShaderSource = +#include "framebuffer.gen.h" +; + +void +GLFrameBuffer::Init(int width, int height) { + + _width = width; + _height = height; + + if (not _program) + _program = compileProgram(g_framebufferShaderSource); + + glGenVertexArrays(1, &_vao); + glBindVertexArray(_vao); + + glGenBuffers(1, &_vbo); + float pos[] = { -1, -1, 1, -1, -1, 1, 1, 1 }; + glGenBuffers(1, &_vbo); + glBindBuffer(GL_ARRAY_BUFFER, _vbo); + glBufferData(GL_ARRAY_BUFFER, sizeof(pos), pos, GL_STATIC_DRAW); + glBindBuffer(GL_ARRAY_BUFFER, _vbo); + + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0); + + glBindVertexArray(0); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + glGenFramebuffers(1, &_frameBuffer); + glGenTextures(1, &_frameBufferColor); + glGenTextures(1, &_frameBufferNormal); + glGenTextures(1, &_frameBufferDepthTexture); + + glBindTexture(GL_TEXTURE_2D, _frameBufferColor); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + + glBindTexture(GL_TEXTURE_2D, _frameBufferNormal); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + + glBindTexture(GL_TEXTURE_2D, _frameBufferDepthTexture); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + + glBindTexture(GL_TEXTURE_2D, 0); + checkGLErrors("FrameBuffer::Init"); +} + +void +GLFrameBuffer::Bind() const { + + glBindFramebuffer(GL_FRAMEBUFFER, _frameBuffer); + + GLenum buffers[2] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1}; + glDrawBuffers(2, buffers); +} + +GLuint +GLFrameBuffer::compileProgram(char const * src) { + + GLuint program = glCreateProgram(); + + std::string vertexSrc = std::string("#define IMAGE_VERTEX_SHADER\n") + src; + GLuint vs = compileShader(GL_VERTEX_SHADER, vertexSrc.c_str()); + + std::string fragmentSrc = std::string("#define IMAGE_FRAGMENT_SHADER\n") + src; + GLuint fs = compileShader(GL_FRAGMENT_SHADER, fragmentSrc.c_str()); + + glAttachShader(program, vs); + glAttachShader(program, fs); + glLinkProgram(program); + + glDeleteShader(vs); + glDeleteShader(fs); + + GLint status; + glGetProgramiv(program, GL_LINK_STATUS, &status); + if (status == GL_FALSE) { + GLint infoLogLength; + glGetProgramiv(_program, GL_INFO_LOG_LENGTH, &infoLogLength); + char *infoLog = new char[infoLogLength]; + glGetProgramInfoLog(_program, infoLogLength, NULL, infoLog); + printf("%s\n", infoLog); + delete[] infoLog; + } + +#if defined(GL_ARB_separate_shader_objects) or defined(GL_VERSION_4_1) + GLint colorMap = glGetUniformLocation(program, "colorMap"); + if (colorMap != -1) + glProgramUniform1i(program, colorMap, 0); // GL_TEXTURE0 + + GLint normalMap = glGetUniformLocation(program, "normalMap"); + if (normalMap != -1) + glProgramUniform1i(program, normalMap, 1); // GL_TEXTURE1 + + GLint depthMap = glGetUniformLocation(program, "depthMap"); + if (depthMap != -1) + glProgramUniform1i(program, depthMap, 2); // GL_TEXTURE2 +#else + glUseProgram(program); + GLint colorMap = glGetUniformLocation(program, "colorMap"); + if (colorMap != -1) + glUniform1i(colorMap, 0); // GL_TEXTURE0 + + GLint colorMap = glGetUniformLocation(program, "normalMap"); + if (normalMap != -1) + glUniform1i(normalMap, 1); // GL_TEXTURE1 + + GLint depthMap = glGetUniformLocation(program, "depthMap"); + if (depthMap != -1) + glUniform1i(depthMap, 2); // GL_TEXTURE2 +#endif + + return program; +} + +void +GLFrameBuffer::ApplyImageShader() { + + glDisable(GL_DEPTH_TEST); + + glBindFramebuffer(GL_FRAMEBUFFER, 0); + glClear(GL_COLOR_BUFFER_BIT); + glViewport(0, 0, GetWidth(), GetHeight()); + + glUseProgram(_program); + + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, _frameBufferColor); + + glActiveTexture(GL_TEXTURE1); + glBindTexture(GL_TEXTURE_2D, _frameBufferNormal); + + glActiveTexture(GL_TEXTURE2); + glBindTexture(GL_TEXTURE_2D, _frameBufferDepthTexture); + + glBindVertexArray(_vao); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + + glBindVertexArray(0); + glUseProgram(0); +} + + +void +GLFrameBuffer::Reshape(int width, int height) { + + // resize framebuffers + glBindTexture(GL_TEXTURE_2D, _frameBufferColor); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, + GL_RGBA, GL_UNSIGNED_BYTE, 0); + + glBindTexture(GL_TEXTURE_2D, _frameBufferNormal); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, + GL_RGB, GL_FLOAT, 0); + + glBindTexture(GL_TEXTURE_2D, _frameBufferDepthTexture); + glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32F, width, height, 0, + GL_DEPTH_COMPONENT, GL_FLOAT, 0); + + glBindFramebuffer(GL_FRAMEBUFFER, _frameBuffer); + + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, + GL_TEXTURE_2D, _frameBufferColor, 0); + + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, + GL_TEXTURE_2D, _frameBufferNormal, 0); + + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, + GL_TEXTURE_2D, _frameBufferDepthTexture, 0); + + GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); + if (status != GL_FRAMEBUFFER_COMPLETE) + assert(false); + + glBindTexture(GL_TEXTURE_2D, 0); + glBindFramebuffer(GL_FRAMEBUFFER, 0); + + _width=width; + _height=height; +} + + +void +GLFrameBuffer::BuildUI(GLhud * /* hud */, int /* x */, int /* y */) { +} + + +void +GLFrameBuffer::Screenshot() const { + +#ifdef OPENSUBDIV_HAS_PNG + + int width = GetWidth(), + height = GetHeight(); + + void * buf = malloc(GetWidth() * GetHeight() * 4 /*RGBA*/); + + glPushClientAttrib(GL_CLIENT_PIXEL_STORE_BIT); + + glPixelStorei(GL_PACK_ROW_LENGTH, 0); + glPixelStorei(GL_PACK_ALIGNMENT, 1); + glPixelStorei(GL_PACK_SKIP_PIXELS, 0); + glPixelStorei(GL_PACK_SKIP_ROWS, 0); + + GLint restoreBinding, restoreActiveTexture; + glGetIntegerv( GL_TEXTURE_BINDING_2D, &restoreBinding ); + glGetIntegerv( GL_ACTIVE_TEXTURE, & restoreActiveTexture); + + glActiveTexture( GL_TEXTURE0 ); + + glBindTexture( GL_TEXTURE_2D, _frameBufferColor ); + glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, buf); + + glActiveTexture( restoreActiveTexture ); + glBindTexture( GL_TEXTURE_2D, restoreBinding ); + glPopClientAttrib(); + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + static int counter=0; + char fname[64]; + snprintf(fname, 64, "screenshot.%d.png", counter++); + + if (FILE * f = fopen( fname, "w" )) { + + png_structp png_ptr = + png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + assert(png_ptr); + + png_infop info_ptr = + png_create_info_struct(png_ptr); + assert(info_ptr); + + png_set_IHDR(png_ptr, info_ptr, width, height, 8, + PNG_COLOR_TYPE_RGB_ALPHA, + PNG_INTERLACE_NONE, + PNG_COMPRESSION_TYPE_DEFAULT, + PNG_FILTER_TYPE_DEFAULT ); + + png_set_compression_level(png_ptr, Z_BEST_COMPRESSION); + + png_bytep rows_ptr[ height ]; + for(int i = 0; iSetActive(value); +} + +static void +callbackSlider(float value, int data) { + + switch (data) { + case 0: g_ssaofb->SetRadius(value); break; + case 1: g_ssaofb->SetScale(value); break; + case 2: g_ssaofb->SetGamma(value); break; + case 3: g_ssaofb->SetContrast(value); break; + default: + assert(0); + } +} + +void +SSAOGLFrameBuffer::BuildUI(GLhud * hud, int x, int y) { + + g_ssaofb = this; + + hud->AddCheckBox("SSAO", _active, x, y, callbackCheckbox); + + hud->AddSlider("Radius", 0.0f, 0.1f, 0.01f, x+20, y+20, 20, false, callbackSlider, 0); + hud->AddSlider("Scale", 1.0f, 1000.0f, 300.0f, x+20, y+60, 20, false, callbackSlider, 1); + //hud->AddSlider("Gamma", 0.0f, 1.0f, 1.0f, x+20, y+100, 20, false, callbackSlider, 2); + //hud->AddSlider("Contrast", 0.0f, 1.0f, 1.0f, x+20, y+140, 20, false, callbackSlider, 3); +} + +void +SSAOGLFrameBuffer::SetActive(bool value) { + + if ( (_active = value) ) { + SSAOGLFrameBuffer::Init(GetWidth(), GetHeight()); + } else { + setProgram( compileProgram(g_framebufferShaderSource) ); + } +} + +void +SSAOGLFrameBuffer::SetRadius(float value) { + + GLuint program = getProgram(); + if (_radius!=-1 and program>0) { +#if defined(GL_ARB_separate_shader_objects) or defined(GL_VERSION_4_1) + glProgramUniform1f(program, _radius, value); +#else + glUseProgram(program); + glUniform1f(_radius, value); +#endif + } +} + +void +SSAOGLFrameBuffer::SetScale(float value) { + + GLuint program = getProgram(); + if (_scale!=-1 and program>0) { +#if defined(GL_ARB_separate_shader_objects) or defined(GL_VERSION_4_1) + glProgramUniform1f(program, _scale, value); +#else + glUseProgram(program); + glUniform1f(_scale, value); +#endif + } +} + +void +SSAOGLFrameBuffer::SetGamma(float value) { + + GLuint program = getProgram(); + if (_gamma!=-1 and program>0) { +#if defined(GL_ARB_separate_shader_objects) or defined(GL_VERSION_4_1) + glProgramUniform1f(program, _gamma, value); +#else + glUseProgram(program); + glUniform1f(_gamma, value); +#endif + } +} + +void +SSAOGLFrameBuffer::SetContrast(float value) { + + GLuint program = getProgram(); + if (_contrast!=-1 and program>0) { +#if defined(GL_ARB_separate_shader_objects) or defined(GL_VERSION_4_1) + glProgramUniform1f(program, _contrast, value); +#else + glUseProgram(program); + glUniform1f(_contrast, value); +#endif + } +} diff --git a/examples/common/gl_framebuffer.h b/examples/common/gl_framebuffer.h new file mode 100644 index 00000000..3c48378a --- /dev/null +++ b/examples/common/gl_framebuffer.h @@ -0,0 +1,128 @@ +// +// Copyright 2013 Pixar +// +// Licensed under the Apache License, Version 2.0 (the "Apache License") +// with the following modification; you may not use this file except in +// compliance with the Apache License and the following modification to it: +// Section 6. Trademarks. is deleted and replaced with: +// +// 6. Trademarks. This License does not grant permission to use the trade +// names, trademarks, service marks, or product names of the Licensor +// and its affiliates, except as required to comply with Section 4(c) of +// the License and to reproduce the content of the NOTICE file. +// +// You may obtain a copy of the Apache License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the Apache License with the above modification is +// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the Apache License for the specific +// language governing permissions and limitations under the Apache License. +// + +#ifndef GL_FRAMEBUFFER_H +#define GL_FRAMEBUFFER_H + +#include + +class GLhud; + +//------------------------------------------------------ +class GLFrameBuffer { + +public: + + int GetWidth() const { + return _width; + } + + int GetHeight() const { + return _height; + } + + virtual void Init(int width, int height); + + virtual void Reshape(int width, int height); + + virtual void ApplyImageShader(); + + virtual void Bind() const; + + virtual void BuildUI(GLhud * hud, int x, int y); + + void Screenshot() const; + +protected: + friend class GLhud; + + GLFrameBuffer(); + virtual ~GLFrameBuffer(); + + GLuint getFrameBuffer() { + return _frameBuffer; + } + + GLuint getProgram() { + return _program; + } + + void setProgram(GLuint program) { + + if (_program) { + glDeleteProgram(_program); + } + _program = program; + } + + GLuint compileProgram(char const * src); + +private: + + int _width, _height; + GLuint _frameBuffer; + GLuint _frameBufferColor; + GLuint _frameBufferNormal; + GLuint _frameBufferDepthTexture; + + GLuint _program; + + GLuint _vao; + GLuint _vbo; +}; + +//------------------------------------------------------ +class SSAOGLFrameBuffer : public GLFrameBuffer { + +public: + + SSAOGLFrameBuffer(); + + virtual void Init(int width, int height); + + virtual void ApplyImageShader(); + + virtual void BuildUI(GLhud * hud, int x, int y); + + void SetActive(bool value); + + void SetRadius(float value); + + void SetScale(float value); + + void SetGamma(float value); + + void SetContrast(float value); + +private: + + bool _active; + + GLint _radius, + _scale, + _gamma, + _contrast; +}; + +#endif // GL_FRAMEBUFFER_H diff --git a/examples/common/gl_hud.cpp b/examples/common/gl_hud.cpp index c2cfc960..4361828a 100644 --- a/examples/common/gl_hud.cpp +++ b/examples/common/gl_hud.cpp @@ -23,12 +23,16 @@ // #include "gl_hud.h" +#include "gl_common.h" #include "font_image.h" #include "simple_math.h" -#include -#include +#include +#include +#include +#include +#include static const char *s_VS = #if defined(GL_VERSION_3_1) @@ -84,7 +88,7 @@ static const char *s_FS = "}\n"; #endif -GLhud::GLhud() : _fontTexture(0), _vbo(0), _staticVbo(0), +GLhud::GLhud() : _frameBuffer(0), _fontTexture(0), _vbo(0), _staticVbo(0), _vao(0), _staticVao(0), _program(0), _aPosition(0), _aColor(0), _aUV(0) { @@ -92,6 +96,8 @@ GLhud::GLhud() : _fontTexture(0), _vbo(0), _staticVbo(0), GLhud::~GLhud() { + if (_frameBuffer) + delete _frameBuffer; if (_program) glDeleteProgram(_program); if (_fontTexture) @@ -106,23 +112,14 @@ GLhud::~GLhud() glDeleteVertexArrays(1, &_staticVao); } -static GLuint compileShader(GLenum shaderType, const char *source) -{ - GLuint shader = glCreateShader(shaderType); - glShaderSource(shader, 1, &source, NULL); - glCompileShader(shader); - - return shader; -} - void GLhud::Init(int width, int height) { Hud::Init(width, height); - + glGenTextures(1, &_fontTexture); glBindTexture(GL_TEXTURE_2D, _fontTexture); - + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); @@ -193,13 +190,21 @@ GLhud::Init(int width, int height) glBindVertexArray(0); glBindBuffer(GL_ARRAY_BUFFER, 0); + + checkGLErrors("GLhud::Init"); + + _frameBuffer = new SSAOGLFrameBuffer; + + _frameBuffer->Init(width, height); + + _frameBuffer->BuildUI(this, 10, 600); } void GLhud::Rebuild(int width, int height) { Hud::Rebuild(width, height); - + if (not _staticVbo) return; @@ -208,12 +213,14 @@ GLhud::Rebuild(int width, int height) glBufferData(GL_ARRAY_BUFFER, _staticVboSize * sizeof(float), &getStaticVboSource()[0], GL_STATIC_DRAW); glBindBuffer(GL_ARRAY_BUFFER, 0); + + GetFrameBuffer()->Reshape(width, height); } bool GLhud::Flush() { - if (!Hud::Flush()) + if (!Hud::Flush()) return false; // update dynamic text @@ -222,12 +229,11 @@ GLhud::Flush() glBufferData(GL_ARRAY_BUFFER, getVboSource().size() * sizeof(float), &getVboSource()[0], GL_STATIC_DRAW); glBindBuffer(GL_ARRAY_BUFFER, 0); - /* (x, y, r, g, b, u, v) = 7*/ + // (x, y, r, g, b, u, v) = 7 int numVertices = (int)getVboSource().size()/7; // reserved space of the vector remains for the next frame. getVboSource().clear(); - glUseProgram(_program); float proj[16]; ortho(proj, 0, 0, float(GetWidth()), float(GetHeight())); @@ -248,3 +254,4 @@ GLhud::Flush() return true; } + diff --git a/examples/common/gl_hud.h b/examples/common/gl_hud.h index 1270988c..7b1d78e8 100644 --- a/examples/common/gl_hud.h +++ b/examples/common/gl_hud.h @@ -29,8 +29,10 @@ #include -class GLhud : public Hud -{ +#include "gl_framebuffer.h" + +class GLhud : public Hud { + public: GLhud(); ~GLhud(); @@ -40,8 +42,16 @@ public: virtual void Rebuild(int width, int height); virtual bool Flush(); - + + GLFrameBuffer * GetFrameBuffer() { + return _frameBuffer; + } + private: + + + GLFrameBuffer * _frameBuffer; + GLuint _fontTexture; GLuint _vbo, _staticVbo; GLuint _vao, _staticVao; diff --git a/examples/common/hud.cpp b/examples/common/hud.cpp index e252602d..392fffca 100644 --- a/examples/common/hud.cpp +++ b/examples/common/hud.cpp @@ -208,7 +208,7 @@ Hud::MouseClick(int x, int y) } void -Hud::MouseMotion(int x, int y) +Hud::MouseMotion(int x, int /* y */) { if (_capturedSlider != -1) { std::vector::iterator it = _sliders.begin() + _capturedSlider; @@ -216,7 +216,7 @@ Hud::MouseMotion(int x, int y) int bx = it->x > 0 ? it->x : _windowWidth + it->x; it->SetValue(((x-bx-FONT_CHAR_WIDTH/2)/float(it->w))*(it->max - it->min) + it->min); it->callback(it->value, it->callbackData); - _requiresRebuildStatic = true; + _requiresRebuildStatic = true; } } diff --git a/examples/common/ssao.glsl b/examples/common/ssao.glsl new file mode 100644 index 00000000..07a308ac --- /dev/null +++ b/examples/common/ssao.glsl @@ -0,0 +1,168 @@ +// +// Copyright 2013 Pixar +// +// Licensed under the Apache License, Version 2.0 (the "Apache License") +// with the following modification; you may not use this file except in +// compliance with the Apache License and the following modification to it: +// Section 6. Trademarks. is deleted and replaced with: +// +// 6. Trademarks. This License does not grant permission to use the trade +// names, trademarks, service marks, or product names of the Licensor +// and its affiliates, except as required to comply with Section 4(c) of +// the License and to reproduce the content of the NOTICE file. +// +// You may obtain a copy of the Apache License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the Apache License with the above modification is +// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the Apache License for the specific +// language governing permissions and limitations under the Apache License. +// + +#version 410 + +//-------------------------------------------------------------- +// image vertex shader +//-------------------------------------------------------------- + +#ifdef IMAGE_VERTEX_SHADER + +layout (location=0) in vec2 position; +out vec2 outUV; + +void +main() +{ + outUV = vec2(position.xy*0.5) + vec2(0.5); + gl_Position = vec4(position.x, position.y, 0, 1); +} + +#endif + +//-------------------------------------------------------------- +#ifdef IMAGE_FRAGMENT_SHADER + +uniform sampler2D colorMap; +uniform sampler2D normalMap; +uniform sampler2D depthMap; + +in vec2 outUV; +out vec4 outColor; + +const vec2 oflut[49] = vec2[]( + vec2(-0.864,-0.930), + vec2(-0.952,-0.608), + vec2(-0.820,-0.318), + vec2(-0.960,-0.076), + vec2(-0.939,0.244), + vec2(-0.827,0.421), + vec2(-0.871,0.561), + vec2(-0.668,-0.810), + vec2(-0.749,-0.557), + vec2(-0.734,-0.422), + vec2(-0.681,-0.043), + vec2(-0.598,0.132), + vec2(-0.720,0.323), + vec2(-0.513,0.723), + vec2(-0.371,-0.829), + vec2(-0.366,-0.735), + vec2(-0.259,-0.318), + vec2(-0.344,-0.079), + vec2(-0.386,0.196), + vec2(-0.405,0.425), + vec2(-0.310,0.518), + vec2(-0.154,-0.931), + vec2(-0.171,-0.572), + vec2(-0.241,-0.420), + vec2(-0.130,-0.225), + vec2(-0.092,0.189), + vec2(-0.018,0.310), + vec2(-0.179,0.512), + vec2(0.133,-0.942), + vec2(0.235,-0.738), + vec2(0.229,-0.380), + vec2(0.027,-0.030), + vec2(0.052,0.183), + vec2(0.141,0.415), + vec2(0.129,0.736), + vec2(0.340,-0.931), + vec2(0.254,-0.564), + vec2(0.388,-0.417), + vec2(0.363,-0.104), + vec2(0.413,0.234), + vec2(0.421,0.321), + vec2(0.423,0.653), + vec2(0.631,-0.756), + vec2(0.665,-0.736), + vec2(0.551,-0.350), + vec2(0.526,-0.220), + vec2(0.519,0.053), + vec2(0.750,0.321), + vec2(0.736,0.641) ); + +float ZBuffer2Linear( float z ,float znear, float zfar) +{ + float z_n = 2.0 * z - 1.0; + float z_e = 2.0 * znear * zfar / (zfar+znear-z_n*(zfar-znear)); + return z_e / 10.0; +} + +uniform float radius; +uniform float scale; +uniform float gamma; +uniform float contrast; + +void main() +{ + + vec4 colorSample = texture(colorMap, outUV); + + float zbuffer = texture(depthMap, outUV).r; + + float rz = ZBuffer2Linear( zbuffer, 1.0, 500.0 ); + + float an = fract(fract(outUV.x*0.36257507)*0.38746515+outUV.y*0.32126721); + + float k1=cos(6.2831*an); + float k2=sin(6.2831*an); + + // calculate occlusion factor + + float ao = 0.0; + for( int i=0; i<49; i++ ) + { + vec2 of = vec2( oflut[i].x*k1 - oflut[i].y*k2, + oflut[i].x*k2 + oflut[i].y*k1 ); + + //sampling point + vec2 sa = outUV.xy + radius * of; + + //difference in zbuffer + float zd = rz - ZBuffer2Linear( texture(depthMap, sa).r, 1.0, 500.0); + + //adjust based on scale. + zd = zd * scale; + + //accumulate zdiffs transfer func + ao += clamp( zd, 0.0, 1.0 ) - clamp((zd-5.0)*.02,0.0,1.0); + } + + //add in occlusion to color. + ao = 1.0 - ao/49.0; + + //scale occlusion toward white. + ao = clamp(ao, 0.0, 1.0); + + //add in contrast/gamma to colorsample. + outColor = contrast*pow(colorSample*ao,vec4(gamma)); + + //background color as a vertical grey ramp + vec4 bgColor = vec4(mix(0.05, 0.25, outUV.y)); + + outColor = mix(bgColor, outColor, colorSample.a); +} + +#endif diff --git a/examples/facePartition/CMakeLists.txt b/examples/facePartition/CMakeLists.txt index 53014d86..9d0e2cd5 100644 --- a/examples/facePartition/CMakeLists.txt +++ b/examples/facePartition/CMakeLists.txt @@ -28,7 +28,7 @@ set(SHADER_FILES shader.glsl ) -set(PLATFORM_LIBRARIES +list(APPEND PLATFORM_LIBRARIES "${OSD_LINK_TARGET}" "${OPENGL_LIBRARY}" "${GLFW_LIBRARIES}" diff --git a/examples/glBatchViewer/CMakeLists.txt b/examples/glBatchViewer/CMakeLists.txt index 697c5206..609aa9d3 100644 --- a/examples/glBatchViewer/CMakeLists.txt +++ b/examples/glBatchViewer/CMakeLists.txt @@ -29,7 +29,7 @@ set(SHADER_FILES shader_gl3.glsl ) -set(PLATFORM_LIBRARIES +list(APPEND PLATFORM_LIBRARIES "${OSD_LINK_TARGET}" "${OPENGL_LIBRARY}" "${GLFW_LIBRARIES}" diff --git a/examples/glStencilViewer/CMakeLists.txt b/examples/glStencilViewer/CMakeLists.txt index 2f0b38ed..8f134aa4 100644 --- a/examples/glStencilViewer/CMakeLists.txt +++ b/examples/glStencilViewer/CMakeLists.txt @@ -24,7 +24,7 @@ # *** glStencilViewer *** -set(PLATFORM_LIBRARIES +list(APPEND PLATFORM_LIBRARIES "${OSD_LINK_TARGET}" "${GLFW_LIBRARIES}" ) diff --git a/examples/glViewer/CMakeLists.txt b/examples/glViewer/CMakeLists.txt index 2195e1a7..2a337f67 100644 --- a/examples/glViewer/CMakeLists.txt +++ b/examples/glViewer/CMakeLists.txt @@ -29,18 +29,18 @@ set(SHADER_FILES shader_gl3.glsl ) -set(PLATFORM_LIBRARIES - "${OSD_LINK_TARGET}" - "${OPENGL_LIBRARY}" - "${GLFW_LIBRARIES}" -) - include_directories( "${PROJECT_SOURCE_DIR}/opensubdiv" "${PROJECT_SOURCE_DIR}/regression" "${GLFW_INCLUDE_DIR}" ) +list(APPEND PLATFORM_LIBRARIES + "${OSD_LINK_TARGET}" + "${OPENGL_LIBRARY}" + "${GLFW_LIBRARIES}" +) + if ( GLEW_FOUND ) include_directories("${GLEW_INCLUDE_DIR}") list(APPEND PLATFORM_LIBRARIES "${GLEW_LIBRARY}") diff --git a/examples/glViewer/shader.glsl b/examples/glViewer/shader.glsl index 0b437acb..10f1ee11 100644 --- a/examples/glViewer/shader.glsl +++ b/examples/glViewer/shader.glsl @@ -300,6 +300,7 @@ in block { } inpt; out vec4 outColor; +out vec3 outNormal; #define NUM_LIGHTS 2 @@ -392,6 +393,7 @@ main() #endif outColor = Cf; + outNormal = N; } #endif diff --git a/examples/glViewer/viewer.cpp b/examples/glViewer/viewer.cpp index 7c7f6648..19e2e099 100644 --- a/examples/glViewer/viewer.cpp +++ b/examples/glViewer/viewer.cpp @@ -264,11 +264,9 @@ checkGLErrors(std::string const & where = "") { GLuint err; while ((err = glGetError()) != GL_NO_ERROR) { - /* std::cerr << "GL error: " << (where.empty() ? "" : where + " ") << err << "\n"; - */ } } @@ -636,7 +634,6 @@ getKernelName(int kernel) { static void createOsdMesh( const std::string &shape, int level, int kernel, Scheme scheme=kCatmark ) { - checkGLErrors("create osd enter"); // generate Hbr representation from "obj" description OsdHbrMesh * hmesh = simpleHbr(shape.c_str(), scheme, g_orgPositions, g_displayStyle == kFaceVaryingColor); @@ -1258,6 +1255,8 @@ bindProgram(Effect effect, OpenSubdiv::OsdDrawContext::PatchArray const & patch) static void display() { + g_hud.GetFrameBuffer()->Bind(); + Stopwatch s; s.Start(); @@ -1275,7 +1274,7 @@ display() { translate(g_transformData.ModelViewMatrix, -g_center[0], -g_center[1], -g_center[2]); perspective(g_transformData.ProjectionMatrix, - 45.0f, (float)aspect, 0.01f, 500.0f); + 45.0f, (float)aspect, 1.0f, 500.0f); multMatrix(g_transformData.ModelViewProjectionMatrix, g_transformData.ModelViewMatrix, g_transformData.ProjectionMatrix); @@ -1286,6 +1285,8 @@ display() { if (g_displayStyle == kVaryingColor) g_mesh->BindVaryingBuffer(); + glEnable(GL_DEPTH_TEST); + glBindVertexArray(g_vao); OpenSubdiv::OsdDrawContext::PatchArrayVector const & patches = g_mesh->GetDrawContext()->patchArrays; @@ -1389,6 +1390,8 @@ display() { if (g_drawCageVertices) drawCageVertices(); + g_hud.GetFrameBuffer()->ApplyImageShader(); + GLuint numPrimsGenerated = 0; GLuint timeElapsed = 0; glGetQueryObjectuiv(g_queries[0], GL_QUERY_RESULT, &numPrimsGenerated); @@ -1450,7 +1453,7 @@ display() { glFinish(); - checkGLErrors("display leave"); + //checkGLErrors("display leave"); } //------------------------------------------------------------------------------ @@ -1461,8 +1464,10 @@ motion(GLFWwindow *, double dx, double dy) { #else motion(int x, int y) { #endif - - if (g_mbutton[0] && !g_mbutton[1] && !g_mbutton[2]) { + if (g_hud.MouseCapture()) { + // check gui + g_hud.MouseMotion(x, y); + } else if (g_mbutton[0] && !g_mbutton[1] && !g_mbutton[2]) { // orbit g_rotate[0] += x - g_prev_x; g_rotate[1] += y - g_prev_y; @@ -1484,11 +1489,14 @@ motion(int x, int y) { //------------------------------------------------------------------------------ static void #if GLFW_VERSION_MAJOR>=3 -mouse(GLFWwindow *, int button, int state, int mods) { +mouse(GLFWwindow *, int button, int state, int /* mods */) { #else mouse(int button, int state) { #endif + if (state == GLFW_RELEASE) + g_hud.MouseRelease(); + if (button == 0 && state == GLFW_PRESS && g_hud.MouseClick(g_prev_x, g_prev_y)) return; @@ -1585,7 +1593,7 @@ toggleFullScreen() { //------------------------------------------------------------------------------ static void #if GLFW_VERSION_MAJOR>=3 -keyboard(GLFWwindow *, int key, int scancode, int event, int mods) { +keyboard(GLFWwindow *, int key, int /* scancode */, int event, int /* mods */) { #else #define GLFW_KEY_ESCAPE GLFW_KEY_ESC keyboard(int key, int event) { @@ -1602,6 +1610,7 @@ keyboard(int key, int event) { case '=': g_tessLevel++; break; case '-': g_tessLevel = std::max(g_tessLevelMin, g_tessLevel-1); break; case GLFW_KEY_ESCAPE: g_hud.SetVisible(!g_hud.IsVisible()); break; + case 'X': g_hud.GetFrameBuffer()->Screenshot(); break; } } @@ -1670,7 +1679,7 @@ callbackModel(int m) } static void -callbackAdaptive(bool checked, int a) +callbackAdaptive(bool checked, int /* a */) { if (OpenSubdiv::OsdGLDrawContext::SupportsAdaptiveTessellation()) { g_adaptive = checked; @@ -1782,14 +1791,14 @@ initHUD() int shapes_pulldown = g_hud.AddPullDown("Shape (N)", -300, 10, 300, callbackModel, 'n'); for (int i = 0; i < (int)g_defaultShapes.size(); ++i) { g_hud.AddPullDownButton(shapes_pulldown, g_defaultShapes[i].name.c_str(),i); - } + } } //------------------------------------------------------------------------------ static void initGL() { - glClearColor(0.1f, 0.1f, 0.1f, 1.0f); + glClearColor(0.1f, 0.1f, 0.1f, 0.0f); glEnable(GL_DEPTH_TEST); glDepthFunc(GL_LEQUAL); glCullFace(GL_BACK); @@ -1843,7 +1852,7 @@ setGLCoreProfile() #else glfwOpenWindowHint(GLFW_OPENGL_VERSION_MINOR, 2); #endif - + #else glfwOpenWindowHint(GLFW_OPENGL_VERSION_MAJOR, 3); glfwOpenWindowHint(GLFW_OPENGL_VERSION_MINOR, 2); diff --git a/examples/limitEval/CMakeLists.txt b/examples/limitEval/CMakeLists.txt index d311d481..101cc3fb 100644 --- a/examples/limitEval/CMakeLists.txt +++ b/examples/limitEval/CMakeLists.txt @@ -24,7 +24,7 @@ # *** glViewer *** -set(PLATFORM_LIBRARIES +list(APPEND PLATFORM_LIBRARIES "${OSD_LINK_TARGET}" "${GLFW_LIBRARIES}" ) diff --git a/examples/paintTest/CMakeLists.txt b/examples/paintTest/CMakeLists.txt index 999b3bfe..4ca0e656 100644 --- a/examples/paintTest/CMakeLists.txt +++ b/examples/paintTest/CMakeLists.txt @@ -29,7 +29,7 @@ set(SHADER_FILES paintShader.glsl ) -set(PLATFORM_LIBRARIES +list(APPEND PLATFORM_LIBRARIES "${OSD_LINK_TARGET}" "${OPENGL_LIBRARY}" "${GLEW_LIBRARY}" diff --git a/examples/ptexViewer/CMakeLists.txt b/examples/ptexViewer/CMakeLists.txt index 86ceba9f..41d4fdc2 100644 --- a/examples/ptexViewer/CMakeLists.txt +++ b/examples/ptexViewer/CMakeLists.txt @@ -31,7 +31,7 @@ set(SHADER_FILES imageshader.glsl ) -set(PLATFORM_LIBRARIES +list(APPEND PLATFORM_LIBRARIES "${OSD_LINK_TARGET}" "${OPENGL_LIBRARY}" "${GLFW_LIBRARIES}" diff --git a/examples/topologySharing/CMakeLists.txt b/examples/topologySharing/CMakeLists.txt index 2a4dcd98..5a5efc17 100644 --- a/examples/topologySharing/CMakeLists.txt +++ b/examples/topologySharing/CMakeLists.txt @@ -28,7 +28,7 @@ set(SHADER_FILES shader.glsl ) -set(PLATFORM_LIBRARIES +list(APPEND PLATFORM_LIBRARIES "${OSD_LINK_TARGET}" "${OPENGL_LIBRARY}" "${GLFW_LIBRARIES}" diff --git a/examples/uvViewer/CMakeLists.txt b/examples/uvViewer/CMakeLists.txt index 5fab5e49..52fce552 100644 --- a/examples/uvViewer/CMakeLists.txt +++ b/examples/uvViewer/CMakeLists.txt @@ -28,7 +28,7 @@ set(SHADER_FILES shader.glsl ) -set(PLATFORM_LIBRARIES +list(APPEND PLATFORM_LIBRARIES "${OSD_LINK_TARGET}" "${OPENGL_LIBRARY}" "${GLFW_LIBRARIES}"