diff --git a/interface/resources/shaders/perlin_modulate.frag b/interface/resources/shaders/perlin_modulate.frag new file mode 100644 index 0000000000..eea0da3671 --- /dev/null +++ b/interface/resources/shaders/perlin_modulate.frag @@ -0,0 +1,63 @@ +#version 120 + +// +// perlin_modulate.frag +// fragment shader +// +// Created by Andrzej Kapolka on 5/15/13. +// Copyright (c) 2013 High Fidelity, Inc. All rights reserved. +// + +// 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; + +// 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 * (1.0 + amplitude*(perlin(position * frequency) - 1.0)), 1.0); +} diff --git a/interface/resources/shaders/perlin_modulate.vert b/interface/resources/shaders/perlin_modulate.vert new file mode 100644 index 0000000000..5cf87fc5fd --- /dev/null +++ b/interface/resources/shaders/perlin_modulate.vert @@ -0,0 +1,20 @@ +#version 120 + +// +// perlin_modulate.vert +// vertex shader +// +// Created by Andrzej Kapolka on 5/15/13. +// Copyright (c) 2013 High Fidelity, Inc. All rights reserved. +// + +// 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/Application.cpp b/interface/src/Application.cpp index 93283eca58..1546d8be13 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -534,10 +534,6 @@ void Application::keyPressEvent(QKeyEvent* event) { shiftPaintingColor(); break; - case Qt::Key_Minus: - sendVoxelServerEraseAll(); - break; - case Qt::Key_Percent: sendVoxelServerAddScene(); break; diff --git a/interface/src/VoxelSystem.cpp b/interface/src/VoxelSystem.cpp index 513253ec19..ac74d81c7f 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(); + _perlinModulateProgram = new ProgramObject(); + _perlinModulateProgram->addShaderFromSourceFile(QGLShader::Vertex, "resources/shaders/perlin_modulate.vert"); + _perlinModulateProgram->addShaderFromSourceFile(QGLShader::Fragment, "resources/shaders/perlin_modulate.frag"); + _perlinModulateProgram->link(); + + _perlinModulateProgram->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); + _perlinModulateProgram->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); + _perlinModulateProgram->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..a3560c1b31 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* _perlinModulateProgram; + GLuint _permutationNormalTextureID; + ViewFrustum* _viewFrustum; ViewFrustum _lastKnowViewFrustum;