From 0a6b4702c6afa062433f167080b61ca4ab7cf42a Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Wed, 15 May 2013 22:18:56 -0700 Subject: [PATCH 1/2] Experimenting with simple Perlin noise shader for voxels. --- .../resources/shaders/grainy_voxels.frag | 57 +++++++++++++++++++ .../resources/shaders/grainy_voxels.vert | 20 +++++++ interface/src/VoxelSystem.cpp | 40 +++++++++++++ interface/src/VoxelSystem.h | 5 ++ 4 files changed, 122 insertions(+) create mode 100644 interface/resources/shaders/grainy_voxels.frag create mode 100644 interface/resources/shaders/grainy_voxels.vert diff --git a/interface/resources/shaders/grainy_voxels.frag b/interface/resources/shaders/grainy_voxels.frag new file mode 100644 index 0000000000..a01de0c577 --- /dev/null +++ b/interface/resources/shaders/grainy_voxels.frag @@ -0,0 +1,57 @@ +// +// grainy_voxels.frag +// fragment shader +// +// Created by Andrzej Kapolka on 5/15/13. +// Copyright (c) 2012 High Fidelity, Inc. All rights reserved. +// + +#version 120 + +// the texture containing our permutations and normals +uniform sampler2D permutationNormalTexture; + +// the position in model space +varying vec3 position; + +// returns the gradient at a single corner of our sampling cube +vec3 grad(vec3 location) { + float p1 = texture2D(permutationNormalTexture, vec2(location.x / 256.0, 0.25)).r; + float p2 = texture2D(permutationNormalTexture, vec2(p1 + location.y / 256.0, 0.25)).r; + return texture2D(permutationNormalTexture, vec2(p2 + location.z / 256.0, 0.75)).xyz * 2.0 - vec3(1.0, 1.0, 1.0); +} + +// returns the perlin noise value for the specified location +float perlin(vec3 location) { + vec3 floors = floor(location); + vec3 ceils = ceil(location); + vec3 fff = grad(floors); + vec3 ffc = grad(vec3(floors.x, floors.y, ceils.z)); + vec3 fcf = grad(vec3(floors.x, ceils.y, floors.z)); + vec3 fcc = grad(vec3(floors.x, ceils.y, ceils.z)); + vec3 cff = grad(vec3(ceils.x, floors.y, floors.z)); + vec3 cfc = grad(vec3(ceils.x, floors.y, ceils.z)); + vec3 ccf = grad(vec3(ceils.x, ceils.y, floors.z)); + vec3 ccc = grad(ceils); + vec3 ffracts = fract(location); + vec3 cfracts = ffracts - vec3(1.0, 1.0, 1.0); + vec3 params = ffracts*ffracts*(3.0 - 2.0*ffracts); + + float fffv = dot(fff, ffracts); + float ffcv = dot(ffc, vec3(ffracts.x, ffracts.y, cfracts.z)); + float fcfv = dot(fcf, vec3(ffracts.x, cfracts.y, ffracts.z)); + float fccv = dot(fcc, vec3(ffracts.x, cfracts.y, cfracts.z)); + float cffv = dot(cff, vec3(cfracts.x, ffracts.y, ffracts.z)); + float cfcv = dot(cfc, vec3(cfracts.x, ffracts.y, cfracts.z)); + float ccfv = dot(ccf, vec3(cfracts.x, cfracts.y, ffracts.z)); + float cccv = dot(ccc, cfracts); + + return mix( + mix(mix(fffv, cffv, params.x), mix(fcfv, ccfv, params.x), params.y), + mix(mix(ffcv, cfcv, params.x), mix(fccv, cccv, params.x), params.y), + params.z); +} + +void main(void) { + gl_FragColor = vec4(gl_Color.rgb * (0.85 + perlin(position * 1024.0) * 0.15), 1.0); +} diff --git a/interface/resources/shaders/grainy_voxels.vert b/interface/resources/shaders/grainy_voxels.vert new file mode 100644 index 0000000000..856b4e7955 --- /dev/null +++ b/interface/resources/shaders/grainy_voxels.vert @@ -0,0 +1,20 @@ +// +// grainy_voxels.vert +// vertex shader +// +// Created by Andrzej Kapolka on 5/15/13. +// Copyright (c) 2013 High Fidelity, Inc. All rights reserved. +// + +#version 120 + +// the position in model space +varying vec3 position; + +void main(void) { + position = gl_Vertex.xyz; + vec4 normal = normalize(gl_ModelViewMatrix * vec4(gl_Normal, 0.0)); + gl_FrontColor = gl_Color * (gl_LightModel.ambient + gl_LightSource[0].ambient + + gl_LightSource[0].diffuse * max(0.0, dot(normal, gl_LightSource[0].position))); + gl_Position = ftransform(); +} diff --git a/interface/src/VoxelSystem.cpp b/interface/src/VoxelSystem.cpp index 513253ec19..7ad967491d 100644 --- a/interface/src/VoxelSystem.cpp +++ b/interface/src/VoxelSystem.cpp @@ -13,6 +13,7 @@ #include #include // to load voxels from file #include // to load voxels from file +#include #include #include #include @@ -20,6 +21,8 @@ #include #include "Log.h" #include "VoxelConstants.h" +#include "InterfaceConfig.h" +#include "renderer/ProgramObject.h" #include "VoxelSystem.h" @@ -497,6 +500,37 @@ void VoxelSystem::init() { // delete the indices and normals arrays that are no longer needed delete[] indicesArray; delete[] normalsArray; + + // create our simple fragment shader + switchToResourcesParentIfRequired(); + _grainProgram = new ProgramObject(); + _grainProgram->addShaderFromSourceFile(QGLShader::Vertex, "resources/shaders/grainy_voxels.vert"); + _grainProgram->addShaderFromSourceFile(QGLShader::Fragment, "resources/shaders/grainy_voxels.frag"); + _grainProgram->link(); + + _grainProgram->setUniformValue("permutationNormalTexture", 0); + + // create the permutation/normal texture + glGenTextures(1, &_permutationNormalTextureID); + glBindTexture(GL_TEXTURE_2D, _permutationNormalTextureID); + + // the first line consists of random permutation offsets + unsigned char data[256 * 2 * 3]; + for (int i = 0; i < 256 * 3; i++) { + data[i] = rand() % 256; + } + // the next, random unit normals + for (int i = 256 * 3; i < 256 * 3 * 2; i += 3) { + glm::vec3 randvec = glm::sphericalRand(1.0f); + data[i] = ((randvec.x + 1.0f) / 2.0f) * 255.0f; + data[i + 1] = ((randvec.y + 1.0f) / 2.0f) * 255.0f; + data[i + 2] = ((randvec.z + 1.0f) / 2.0f) * 255.0f; + } + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 256, 2, 0, GL_RGB, GL_UNSIGNED_BYTE, data); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + + glBindTexture(GL_TEXTURE_2D, 0); } void VoxelSystem::updateFullVBOs() { @@ -606,11 +640,17 @@ void VoxelSystem::render() { glBindBuffer(GL_ARRAY_BUFFER, _vboColorsID); glColorPointer(3, GL_UNSIGNED_BYTE, 0, 0); + _grainProgram->bind(); + glBindTexture(GL_TEXTURE_2D, _permutationNormalTextureID); + // draw the number of voxels we have glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _vboIndicesID); glScalef(TREE_SCALE, TREE_SCALE, TREE_SCALE); glDrawElements(GL_TRIANGLES, 36 * _voxelsInReadArrays, GL_UNSIGNED_INT, 0); + _grainProgram->release(); + glBindTexture(GL_TEXTURE_2D, 0); + // deactivate vertex and color arrays after drawing glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_NORMAL_ARRAY); diff --git a/interface/src/VoxelSystem.h b/interface/src/VoxelSystem.h index 50997d84bf..61ed570563 100644 --- a/interface/src/VoxelSystem.h +++ b/interface/src/VoxelSystem.h @@ -21,6 +21,8 @@ #include "Util.h" #include "world.h" +class ProgramObject; + const int NUM_CHILDREN = 8; class VoxelSystem : public AgentData { @@ -133,6 +135,9 @@ private: pthread_mutex_t _bufferWriteLock; pthread_mutex_t _treeLock; + ProgramObject* _grainProgram; + GLuint _permutationNormalTextureID; + ViewFrustum* _viewFrustum; ViewFrustum _lastKnowViewFrustum; From 86ddcea87f673701a4a58ce9051aa3728687d066 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Thu, 16 May 2013 13:08:21 -0700 Subject: [PATCH 2/2] Better names for the shaders. --- .../{grainy_voxels.frag => perlin_modulate.frag} | 16 +++++++++++----- .../{grainy_voxels.vert => perlin_modulate.vert} | 6 +++--- interface/src/VoxelSystem.cpp | 14 +++++++------- interface/src/VoxelSystem.h | 2 +- 4 files changed, 22 insertions(+), 16 deletions(-) rename interface/resources/shaders/{grainy_voxels.frag => perlin_modulate.frag} (87%) rename interface/resources/shaders/{grainy_voxels.vert => perlin_modulate.vert} (95%) diff --git a/interface/resources/shaders/grainy_voxels.frag b/interface/resources/shaders/perlin_modulate.frag similarity index 87% rename from interface/resources/shaders/grainy_voxels.frag rename to interface/resources/shaders/perlin_modulate.frag index a01de0c577..eea0da3671 100644 --- a/interface/resources/shaders/grainy_voxels.frag +++ b/interface/resources/shaders/perlin_modulate.frag @@ -1,16 +1,22 @@ +#version 120 + // -// grainy_voxels.frag +// perlin_modulate.frag // fragment shader // // Created by Andrzej Kapolka on 5/15/13. -// Copyright (c) 2012 High Fidelity, Inc. All rights reserved. +// Copyright (c) 2013 High Fidelity, Inc. All rights reserved. // -#version 120 - // the texture containing our permutations and normals uniform sampler2D permutationNormalTexture; +// the noise frequency +const float frequency = 1024.0; + +// the noise amplitude +const float amplitude = 0.1; + // the position in model space varying vec3 position; @@ -53,5 +59,5 @@ float perlin(vec3 location) { } void main(void) { - gl_FragColor = vec4(gl_Color.rgb * (0.85 + perlin(position * 1024.0) * 0.15), 1.0); + gl_FragColor = vec4(gl_Color.rgb * (1.0 + amplitude*(perlin(position * frequency) - 1.0)), 1.0); } diff --git a/interface/resources/shaders/grainy_voxels.vert b/interface/resources/shaders/perlin_modulate.vert similarity index 95% rename from interface/resources/shaders/grainy_voxels.vert rename to interface/resources/shaders/perlin_modulate.vert index 856b4e7955..5cf87fc5fd 100644 --- a/interface/resources/shaders/grainy_voxels.vert +++ b/interface/resources/shaders/perlin_modulate.vert @@ -1,13 +1,13 @@ +#version 120 + // -// grainy_voxels.vert +// perlin_modulate.vert // vertex shader // // Created by Andrzej Kapolka on 5/15/13. // Copyright (c) 2013 High Fidelity, Inc. All rights reserved. // -#version 120 - // the position in model space varying vec3 position; diff --git a/interface/src/VoxelSystem.cpp b/interface/src/VoxelSystem.cpp index 7ad967491d..ac74d81c7f 100644 --- a/interface/src/VoxelSystem.cpp +++ b/interface/src/VoxelSystem.cpp @@ -503,12 +503,12 @@ void VoxelSystem::init() { // create our simple fragment shader switchToResourcesParentIfRequired(); - _grainProgram = new ProgramObject(); - _grainProgram->addShaderFromSourceFile(QGLShader::Vertex, "resources/shaders/grainy_voxels.vert"); - _grainProgram->addShaderFromSourceFile(QGLShader::Fragment, "resources/shaders/grainy_voxels.frag"); - _grainProgram->link(); + _perlinModulateProgram = new ProgramObject(); + _perlinModulateProgram->addShaderFromSourceFile(QGLShader::Vertex, "resources/shaders/perlin_modulate.vert"); + _perlinModulateProgram->addShaderFromSourceFile(QGLShader::Fragment, "resources/shaders/perlin_modulate.frag"); + _perlinModulateProgram->link(); - _grainProgram->setUniformValue("permutationNormalTexture", 0); + _perlinModulateProgram->setUniformValue("permutationNormalTexture", 0); // create the permutation/normal texture glGenTextures(1, &_permutationNormalTextureID); @@ -640,7 +640,7 @@ void VoxelSystem::render() { glBindBuffer(GL_ARRAY_BUFFER, _vboColorsID); glColorPointer(3, GL_UNSIGNED_BYTE, 0, 0); - _grainProgram->bind(); + _perlinModulateProgram->bind(); glBindTexture(GL_TEXTURE_2D, _permutationNormalTextureID); // draw the number of voxels we have @@ -648,7 +648,7 @@ void VoxelSystem::render() { glScalef(TREE_SCALE, TREE_SCALE, TREE_SCALE); glDrawElements(GL_TRIANGLES, 36 * _voxelsInReadArrays, GL_UNSIGNED_INT, 0); - _grainProgram->release(); + _perlinModulateProgram->release(); glBindTexture(GL_TEXTURE_2D, 0); // deactivate vertex and color arrays after drawing diff --git a/interface/src/VoxelSystem.h b/interface/src/VoxelSystem.h index 61ed570563..a3560c1b31 100644 --- a/interface/src/VoxelSystem.h +++ b/interface/src/VoxelSystem.h @@ -135,7 +135,7 @@ private: pthread_mutex_t _bufferWriteLock; pthread_mutex_t _treeLock; - ProgramObject* _grainProgram; + ProgramObject* _perlinModulateProgram; GLuint _permutationNormalTextureID; ViewFrustum* _viewFrustum;