From eb6af1afbfa037e4353dea7c56d04d62c5f73810 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Fri, 27 Sep 2013 09:02:51 -0700 Subject: [PATCH 1/3] fix byte normals, fix crashes in switching between voxel shader and normal mode --- interface/src/VoxelSystem.cpp | 75 +++++++++++++++++++++++++------- interface/src/VoxelSystem.h | 4 ++ libraries/voxels/src/VoxelNode.h | 1 + 3 files changed, 65 insertions(+), 15 deletions(-) diff --git a/interface/src/VoxelSystem.cpp b/interface/src/VoxelSystem.cpp index fe82da66a0..ed8de7f8a5 100644 --- a/interface/src/VoxelSystem.cpp +++ b/interface/src/VoxelSystem.cpp @@ -37,7 +37,7 @@ float identityVertices[] = { 0,0,0, 1,0,0, 1,1,0, 0,1,0, 0,0,1, 1,0,1, 1,1,1, 0, 0,0,0, 1,0,0, 1,1,0, 0,1,0, 0,0,1, 1,0,1, 1,1,1, 0,1,1, 0,0,0, 1,0,0, 1,1,0, 0,1,0, 0,0,1, 1,0,1, 1,1,1, 0,1,1 }; -GLbyte identityNormals[] = { 0,0,-1, 0,0,-1, 0,0,-1, 0,0,-1, +GLfloat identityNormals[] = { 0,0,-1, 0,0,-1, 0,0,-1, 0,0,-1, 0,0,+1, 0,0,+1, 0,0,+1, 0,0,+1, 0,-1,0, 0,-1,0, 0,+1,0, 0,+1,0, 0,-1,0, 0,-1,0, 0,+1,0, 0,+1,0, @@ -152,6 +152,10 @@ void VoxelSystem::setUseByteNormals(bool useByteNormals) { init(); } pthread_mutex_unlock(&_bufferWriteLock); + + if (wasInitialized) { + forceRedrawEntireTree(); + } } @@ -166,12 +170,17 @@ void VoxelSystem::setMaxVoxels(int maxVoxels) { init(); } pthread_mutex_unlock(&_bufferWriteLock); + + if (wasInitialized) { + forceRedrawEntireTree(); + } } void VoxelSystem::setUseVoxelShader(bool useVoxelShader) { pthread_mutex_lock(&_bufferWriteLock); bool wasInitialized = _initialized; if (wasInitialized) { + clearAllNodesBufferIndex(); cleanupVoxelMemory(); } _useVoxelShader = useVoxelShader; @@ -179,6 +188,10 @@ void VoxelSystem::setUseVoxelShader(bool useVoxelShader) { init(); } pthread_mutex_unlock(&_bufferWriteLock); + + if (wasInitialized) { + forceRedrawEntireTree(); + } } void VoxelSystem::cleanupVoxelMemory() { @@ -266,7 +279,7 @@ void VoxelSystem::initVoxelMemory() { // populate the normalsArray for (int n = 0; n < _maxVoxels; n++) { for (int i = 0; i < VERTEX_POINTS_PER_VOXEL; i++) { - *(normalsArrayEndPointer++) = identityNormals[i]; + *(normalsArrayEndPointer++) = (identityNormals[i] * CHAR_MAX); } } @@ -750,20 +763,24 @@ void VoxelSystem::updateNodeInArrays(glBufferIndex nodeIndex, const glm::vec3& s float voxelScale, const nodeColor& color) { if (_useVoxelShader) { - VoxelShaderVBOData* writeVerticesAt = &_writeVoxelShaderData[nodeIndex]; - writeVerticesAt->x = startVertex.x * TREE_SCALE; - writeVerticesAt->y = startVertex.y * TREE_SCALE; - writeVerticesAt->z = startVertex.z * TREE_SCALE; - writeVerticesAt->s = voxelScale * TREE_SCALE; - writeVerticesAt->r = color[RED_INDEX]; - writeVerticesAt->g = color[GREEN_INDEX]; - writeVerticesAt->b = color[BLUE_INDEX]; + if (_writeVoxelShaderData) { + VoxelShaderVBOData* writeVerticesAt = &_writeVoxelShaderData[nodeIndex]; + writeVerticesAt->x = startVertex.x * TREE_SCALE; + writeVerticesAt->y = startVertex.y * TREE_SCALE; + writeVerticesAt->z = startVertex.z * TREE_SCALE; + writeVerticesAt->s = voxelScale * TREE_SCALE; + writeVerticesAt->r = color[RED_INDEX]; + writeVerticesAt->g = color[GREEN_INDEX]; + writeVerticesAt->b = color[BLUE_INDEX]; + } } else { - for (int j = 0; j < VERTEX_POINTS_PER_VOXEL; j++ ) { - GLfloat* writeVerticesAt = _writeVerticesArray + (nodeIndex * VERTEX_POINTS_PER_VOXEL); - GLubyte* writeColorsAt = _writeColorsArray + (nodeIndex * VERTEX_POINTS_PER_VOXEL); - *(writeVerticesAt+j) = startVertex[j % 3] + (identityVertices[j] * voxelScale); - *(writeColorsAt +j) = color[j % 3]; + if (_writeVerticesArray && _writeColorsArray) { + for (int j = 0; j < VERTEX_POINTS_PER_VOXEL; j++ ) { + GLfloat* writeVerticesAt = _writeVerticesArray + (nodeIndex * VERTEX_POINTS_PER_VOXEL); + GLubyte* writeColorsAt = _writeColorsArray + (nodeIndex * VERTEX_POINTS_PER_VOXEL); + *(writeVerticesAt+j) = startVertex[j % 3] + (identityVertices[j] * voxelScale); + *(writeColorsAt +j) = color[j % 3]; + } } } } @@ -995,6 +1012,34 @@ void VoxelSystem::killLocalVoxels() { } +bool VoxelSystem::clearAllNodesBufferIndexOperation(VoxelNode* node, void* extraData) { + _nodeCount++; + node->setBufferIndex(GLBUFFER_INDEX_UNKNOWN); + return true; +} + +void VoxelSystem::clearAllNodesBufferIndex() { + _nodeCount = 0; + _tree->recurseTreeWithOperation(clearAllNodesBufferIndexOperation); + qDebug("clearing buffer index of %d nodes\n", _nodeCount); + _tree->setDirtyBit(); + setupNewVoxelsForDrawing(); +} + +bool VoxelSystem::forceRedrawEntireTreeOperation(VoxelNode* node, void* extraData) { + _nodeCount++; + node->setDirtyBit(); + return true; +} + +void VoxelSystem::forceRedrawEntireTree() { + _nodeCount = 0; + _tree->recurseTreeWithOperation(forceRedrawEntireTreeOperation); + qDebug("forcing redraw of %d nodes\n", _nodeCount); + _tree->setDirtyBit(); + setupNewVoxelsForDrawing(); +} + bool VoxelSystem::randomColorOperation(VoxelNode* node, void* extraData) { _nodeCount++; if (node->isColored()) { diff --git a/interface/src/VoxelSystem.h b/interface/src/VoxelSystem.h index 5d3ac96d8c..39807f918e 100644 --- a/interface/src/VoxelSystem.h +++ b/interface/src/VoxelSystem.h @@ -126,6 +126,8 @@ public slots: void falseColorizeOccluded(); void falseColorizeOccludedV2(); void falseColorizeBySource(); + void forceRedrawEntireTree(); + void clearAllNodesBufferIndex(); void cancelImport(); void setUseByteNormals(bool useByteNormals); @@ -172,6 +174,8 @@ private: static bool falseColorizeOccludedV2Operation(VoxelNode* node, void* extraData); static bool falseColorizeBySourceOperation(VoxelNode* node, void* extraData); static bool killSourceVoxelsOperation(VoxelNode* node, void* extraData); + static bool forceRedrawEntireTreeOperation(VoxelNode* node, void* extraData); + static bool clearAllNodesBufferIndexOperation(VoxelNode* node, void* extraData); int updateNodeInArraysAsFullVBO(VoxelNode* node); int updateNodeInArraysAsPartialVBO(VoxelNode* node); diff --git a/libraries/voxels/src/VoxelNode.h b/libraries/voxels/src/VoxelNode.h index b7f31e3b61..03a8fe3c57 100644 --- a/libraries/voxels/src/VoxelNode.h +++ b/libraries/voxels/src/VoxelNode.h @@ -70,6 +70,7 @@ public: void printDebugDetails(const char* label) const; bool isDirty() const { return _isDirty; } void clearDirtyBit() { _isDirty = false; } + void setDirtyBit() { _isDirty = true; } bool hasChangedSince(uint64_t time) const { return (_lastChanged > time); } void markWithChangedTime() { _lastChanged = usecTimestampNow(); } uint64_t getLastChanged() const { return _lastChanged; } From 605c2f30cfb8fc9820f44bb3d3fea5638f30233c Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Fri, 27 Sep 2013 10:17:10 -0700 Subject: [PATCH 2/3] add memory usage debugging --- interface/src/Application.cpp | 20 ++++++--- interface/src/VoxelSystem.cpp | 85 +++++++++++++++++++++++++++++++++-- interface/src/VoxelSystem.h | 10 +++++ 3 files changed, 105 insertions(+), 10 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 7bf76466bc..7c223043d4 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2822,28 +2822,36 @@ void Application::displayStats() { voxelStats << "Voxels Rendered: " << _voxels.getVoxelsRendered() / 1000.f << "K " << "Updated: " << _voxels.getVoxelsUpdated()/1000.f << "K " << "Max: " << _voxels.getMaxVoxels()/1000.f << "K "; - drawtext(10, statsVerticalOffset + 230, 0.10f, 0, 1.0, 0, (char *)voxelStats.str().c_str()); + + voxelStats.str(""); + voxelStats << "Voxels Memory RAM: " << _voxels.getVoxelMemoryUsageRAM() / 1000000.f << "MB " << + "VBO: " << _voxels.getVoxelMemoryUsageVBO() / 1000000.f << "MB "; + if (_voxels.hasVoxelMemoryUsageGPU()) { + voxelStats << "GPU: " << _voxels.getVoxelMemoryUsageGPU() / 1000000.f << "MB "; + } + + drawtext(10, statsVerticalOffset + 250, 0.10f, 0, 1.0, 0, (char *)voxelStats.str().c_str()); voxelStats.str(""); char* voxelDetails = _voxelSceneStats.getItemValue(VoxelSceneStats::ITEM_VOXELS); voxelStats << "Voxels Sent from Server: " << voxelDetails; - drawtext(10, statsVerticalOffset + 250, 0.10f, 0, 1.0, 0, (char *)voxelStats.str().c_str()); + drawtext(10, statsVerticalOffset + 270, 0.10f, 0, 1.0, 0, (char *)voxelStats.str().c_str()); voxelStats.str(""); voxelDetails = _voxelSceneStats.getItemValue(VoxelSceneStats::ITEM_ELAPSED); voxelStats << "Scene Send Time from Server: " << voxelDetails; - drawtext(10, statsVerticalOffset + 270, 0.10f, 0, 1.0, 0, (char *)voxelStats.str().c_str()); + drawtext(10, statsVerticalOffset + 290, 0.10f, 0, 1.0, 0, (char *)voxelStats.str().c_str()); voxelStats.str(""); voxelDetails = _voxelSceneStats.getItemValue(VoxelSceneStats::ITEM_ENCODE); voxelStats << "Encode Time on Server: " << voxelDetails; - drawtext(10, statsVerticalOffset + 290, 0.10f, 0, 1.0, 0, (char *)voxelStats.str().c_str()); + drawtext(10, statsVerticalOffset + 310, 0.10f, 0, 1.0, 0, (char *)voxelStats.str().c_str()); voxelStats.str(""); voxelDetails = _voxelSceneStats.getItemValue(VoxelSceneStats::ITEM_MODE); voxelStats << "Sending Mode: " << voxelDetails; - drawtext(10, statsVerticalOffset + 310, 0.10f, 0, 1.0, 0, (char *)voxelStats.str().c_str()); + drawtext(10, statsVerticalOffset + 330, 0.10f, 0, 1.0, 0, (char *)voxelStats.str().c_str()); Node *avatarMixer = NodeList::getInstance()->soloNodeOfType(NODE_TYPE_AVATAR_MIXER); char avatarMixerStats[200]; @@ -2856,7 +2864,7 @@ void Application::displayStats() { sprintf(avatarMixerStats, "No Avatar Mixer"); } - drawtext(10, statsVerticalOffset + 330, 0.10f, 0, 1.0, 0, avatarMixerStats); + drawtext(10, statsVerticalOffset + 350, 0.10f, 0, 1.0, 0, avatarMixerStats); drawtext(10, statsVerticalOffset + 450, 0.10f, 0, 1.0, 0, (char *)LeapManager::statusString().c_str()); if (_perfStatsOn) { diff --git a/interface/src/VoxelSystem.cpp b/interface/src/VoxelSystem.cpp index ed8de7f8a5..88661dd2bd 100644 --- a/interface/src/VoxelSystem.cpp +++ b/interface/src/VoxelSystem.cpp @@ -214,14 +214,17 @@ void VoxelSystem::cleanupVoxelMemory() { delete[] _writeVerticesArray; delete[] _readColorsArray; delete[] _writeColorsArray; - delete[] _writeVoxelDirtyArray; - delete[] _readVoxelDirtyArray; } + delete[] _writeVoxelDirtyArray; + delete[] _readVoxelDirtyArray; } _initialized = false; // no longer initialized } void VoxelSystem::initVoxelMemory() { + _initialMemoryUsageGPU = getFreeMemoryGPU(); + _memoryUsageRAM = 0; + _memoryUsageVBO = 0; // our VBO allocations as we know them if (_useVoxelShader) { qDebug("Using Voxel Shader...\n"); GLuint* indicesArray = new GLuint[_maxVoxels]; @@ -235,12 +238,13 @@ void VoxelSystem::initVoxelMemory() { // bind the indices VBO to the actual indices array glGenBuffers(1, &_vboVoxelsIndicesID); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _vboVoxelsIndicesID); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, _maxVoxels, indicesArray, GL_STATIC_DRAW); - + glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLuint) * _maxVoxels, indicesArray, GL_STATIC_DRAW); + _memoryUsageVBO += sizeof(GLuint) * _maxVoxels; glGenBuffers(1, &_vboVoxelsID); glBindBuffer(GL_ARRAY_BUFFER, _vboVoxelsID); glBufferData(GL_ARRAY_BUFFER, _maxVoxels * sizeof(VoxelShaderVBOData), NULL, GL_DYNAMIC_DRAW); + _memoryUsageVBO += _maxVoxels * sizeof(VoxelShaderVBOData); // delete the indices and normals arrays that are no longer needed delete[] indicesArray; @@ -248,12 +252,18 @@ void VoxelSystem::initVoxelMemory() { // we will track individual dirty sections with these arrays of bools _writeVoxelDirtyArray = new bool[_maxVoxels]; memset(_writeVoxelDirtyArray, false, _maxVoxels * sizeof(bool)); + _memoryUsageRAM += (_maxVoxels * sizeof(bool)); + _readVoxelDirtyArray = new bool[_maxVoxels]; memset(_readVoxelDirtyArray, false, _maxVoxels * sizeof(bool)); + _memoryUsageRAM += (_maxVoxels * sizeof(bool)); // prep the data structures for incoming voxel data _writeVoxelShaderData = new VoxelShaderVBOData[_maxVoxels]; + _memoryUsageRAM += (sizeof(VoxelShaderVBOData) * _maxVoxels); + _readVoxelShaderData = new VoxelShaderVBOData[_maxVoxels]; + _memoryUsageRAM += (sizeof(VoxelShaderVBOData) * _maxVoxels); } else { GLuint* indicesArray = new GLuint[INDICES_PER_VOXEL * _maxVoxels]; @@ -289,6 +299,7 @@ void VoxelSystem::initVoxelMemory() { glBufferData(GL_ARRAY_BUFFER, VERTEX_POINTS_PER_VOXEL * sizeof(GLbyte) * _maxVoxels, normalsArray, GL_STATIC_DRAW); + _memoryUsageVBO += VERTEX_POINTS_PER_VOXEL * sizeof(GLbyte) * _maxVoxels; // delete the indices and normals arrays that are no longer needed delete[] normalsArray; @@ -310,6 +321,7 @@ void VoxelSystem::initVoxelMemory() { glBufferData(GL_ARRAY_BUFFER, VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat) * _maxVoxels, normalsArray, GL_STATIC_DRAW); + _memoryUsageVBO += VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat) * _maxVoxels; // delete the indices and normals arrays that are no longer needed delete[] normalsArray; @@ -319,11 +331,13 @@ void VoxelSystem::initVoxelMemory() { glGenBuffers(1, &_vboVerticesID); glBindBuffer(GL_ARRAY_BUFFER, _vboVerticesID); glBufferData(GL_ARRAY_BUFFER, VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat) * _maxVoxels, NULL, GL_DYNAMIC_DRAW); + _memoryUsageVBO += VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat) * _maxVoxels; // VBO for colorsArray glGenBuffers(1, &_vboColorsID); glBindBuffer(GL_ARRAY_BUFFER, _vboColorsID); glBufferData(GL_ARRAY_BUFFER, VERTEX_POINTS_PER_VOXEL * sizeof(GLubyte) * _maxVoxels, NULL, GL_DYNAMIC_DRAW); + _memoryUsageVBO += VERTEX_POINTS_PER_VOXEL * sizeof(GLubyte) * _maxVoxels; // VBO for the indicesArray glGenBuffers(1, &_vboIndicesID); @@ -331,6 +345,7 @@ void VoxelSystem::initVoxelMemory() { glBufferData(GL_ELEMENT_ARRAY_BUFFER, INDICES_PER_VOXEL * sizeof(GLuint) * _maxVoxels, indicesArray, GL_STATIC_DRAW); + _memoryUsageVBO += INDICES_PER_VOXEL * sizeof(GLuint) * _maxVoxels; // delete the indices and normals arrays that are no longer needed delete[] indicesArray; @@ -339,15 +354,22 @@ void VoxelSystem::initVoxelMemory() { // we will track individual dirty sections with these arrays of bools _writeVoxelDirtyArray = new bool[_maxVoxels]; memset(_writeVoxelDirtyArray, false, _maxVoxels * sizeof(bool)); + _memoryUsageRAM += (sizeof(bool) * _maxVoxels); + _readVoxelDirtyArray = new bool[_maxVoxels]; memset(_readVoxelDirtyArray, false, _maxVoxels * sizeof(bool)); + _memoryUsageRAM += (sizeof(bool) * _maxVoxels); // prep the data structures for incoming voxel data _writeVerticesArray = new GLfloat[VERTEX_POINTS_PER_VOXEL * _maxVoxels]; + _memoryUsageRAM += (sizeof(GLfloat) * VERTEX_POINTS_PER_VOXEL * _maxVoxels); _readVerticesArray = new GLfloat[VERTEX_POINTS_PER_VOXEL * _maxVoxels]; + _memoryUsageRAM += (sizeof(GLfloat) * VERTEX_POINTS_PER_VOXEL * _maxVoxels); _writeColorsArray = new GLubyte[VERTEX_POINTS_PER_VOXEL * _maxVoxels]; + _memoryUsageRAM += (sizeof(GLubyte) * VERTEX_POINTS_PER_VOXEL * _maxVoxels); _readColorsArray = new GLubyte[VERTEX_POINTS_PER_VOXEL * _maxVoxels]; + _memoryUsageRAM += (sizeof(GLubyte) * VERTEX_POINTS_PER_VOXEL * _maxVoxels); // create our simple fragment shader if we're the first system to init @@ -1897,3 +1919,58 @@ void VoxelSystem::nodeKilled(Node* node) { } +unsigned long VoxelSystem::getFreeMemoryGPU() { + // We can't ask all GPUs how much memory they have in use, but we can ask them about how much is free. + // So, we can record the free memory before we create our VBOs and the free memory after, and get a basic + // idea how how much we're using. + + _hasMemoryUsageGPU = false; // assume the worst + unsigned long freeMemory = 0; + const int NUM_RESULTS = 4; // see notes, these APIs return up to 4 results + GLint results[NUM_RESULTS] = { 0, 0, 0, 0}; + + // ATI + // http://www.opengl.org/registry/specs/ATI/meminfo.txt + // + // TEXTURE_FREE_MEMORY_ATI 0x87FC + // RENDERBUFFER_FREE_MEMORY_ATI 0x87FD + const GLenum VBO_FREE_MEMORY_ATI = 0x87FB; + glGetIntegerv(VBO_FREE_MEMORY_ATI, &results[0]); + GLenum errorATI = glGetError(); + + if (errorATI == GL_NO_ERROR) { + _hasMemoryUsageGPU = true; + freeMemory = results[0]; + } else { + + // NVIDIA + // http://developer.download.nvidia.com/opengl/specs/GL_NVX_gpu_memory_info.txt + // + //const GLenum GPU_MEMORY_INFO_DEDICATED_VIDMEM_NVX = 0x9047; + //const GLenum GPU_MEMORY_INFO_EVICTION_COUNT_NVX = 0x904A; + //const GLenum GPU_MEMORY_INFO_EVICTED_MEMORY_NVX = 0x904B; + //const GLenum GPU_MEMORY_INFO_TOTAL_AVAILABLE_MEMORY_NVX = 0x9048; + + const GLenum GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX = 0x9049; + results[0] = 0; + glGetIntegerv(GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX, &results[0]); + freeMemory += results[0]; + GLenum errorNVIDIA = glGetError(); + + if (errorNVIDIA == GL_NO_ERROR) { + _hasMemoryUsageGPU = true; + freeMemory = results[0]; + } + } + + const unsigned long BYTES_PER_KBYTE = 1024; + return freeMemory * BYTES_PER_KBYTE; // API results in KB, we want it in bytes +} + +unsigned long VoxelSystem::getVoxelMemoryUsageGPU() { + unsigned long currentFreeMemory = getFreeMemoryGPU(); + return (_initialMemoryUsageGPU - currentFreeMemory); +} + + + diff --git a/interface/src/VoxelSystem.h b/interface/src/VoxelSystem.h index 39807f918e..5e56cfe8a6 100644 --- a/interface/src/VoxelSystem.h +++ b/interface/src/VoxelSystem.h @@ -69,6 +69,10 @@ public: void setMaxVoxels(int maxVoxels); long int getMaxVoxels() const { return _maxVoxels; } + unsigned long getVoxelMemoryUsageRAM() const { return _memoryUsageRAM; } + unsigned long getVoxelMemoryUsageVBO() const { return _memoryUsageVBO; } + bool hasVoxelMemoryUsageGPU() const { return _hasMemoryUsageGPU; } + unsigned long getVoxelMemoryUsageGPU(); long int getVoxelsCreated(); long int getVoxelsColored(); long int getVoxelsBytesRead(); @@ -185,6 +189,8 @@ private: void updateVBOs(); + unsigned long getFreeMemoryGPU(); + // these are kinda hacks, used by getDistanceFromViewRangeOperation() probably shouldn't be here static float _maxDistance; static float _minDistance; @@ -253,6 +259,10 @@ private: int _dataSourceID; int _voxelServerCount; + unsigned long _memoryUsageRAM; + unsigned long _memoryUsageVBO; + unsigned long _initialMemoryUsageGPU; + bool _hasMemoryUsageGPU; }; #endif From dbfc0956c1bfcf1de89b7658081a90d5eab9b62d Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Fri, 27 Sep 2013 13:26:58 -0700 Subject: [PATCH 3/3] added normals to voxel shader --- interface/resources/shaders/voxel.geom | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/interface/resources/shaders/voxel.geom b/interface/resources/shaders/voxel.geom index 13b502357e..ca8f729542 100644 --- a/interface/resources/shaders/voxel.geom +++ b/interface/resources/shaders/voxel.geom @@ -26,14 +26,17 @@ const int VERTICES_PER_FACE = 4; const int COORD_PER_VERTEX = 3; const int COORD_PER_FACE = COORD_PER_VERTEX * VERTICES_PER_FACE; -void faceOfVoxel(vec4 corner, float scale, float[COORD_PER_FACE] facePoints, vec4 color) { +void faceOfVoxel(vec4 corner, float scale, float[COORD_PER_FACE] facePoints, vec4 color, vec4 normal) { for (int v = 0; v < VERTICES_PER_FACE; v++ ) { vec4 vertex = corner; for (int c = 0; c < COORD_PER_VERTEX; c++ ) { int cIndex = c + (v * COORD_PER_VERTEX); vertex[c] += (facePoints[cIndex] * scale); } - gl_FrontColor = color; + + gl_FrontColor = color * (gl_LightModel.ambient + gl_LightSource[0].ambient + + gl_LightSource[0].diffuse * max(0.0, dot(normal, gl_LightSource[0].position))); + gl_Position = gl_ModelViewProjectionMatrix * vertex; EmitVertex(); } @@ -54,14 +57,21 @@ void main() { float frontFace[COORD_PER_FACE] = float[COORD_PER_FACE]( 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0 ); float backFace[COORD_PER_FACE] = float[COORD_PER_FACE]( 1, 0, 1, 0, 0, 1, 1, 1, 1, 0, 1, 1 ); + vec4 bottomNormal = vec4(0.0, -1, 0.0, 0.0); + vec4 topNormal = vec4(0.0, 1, 0.0, 0.0); + vec4 rightNormal = vec4( -1, 0.0, 0.0, 0.0); + vec4 leftNormal = vec4( 1, 0.0, 0.0, 0.0); + vec4 frontNormal = vec4(0.0, 0.0, -1, 0.0); + vec4 backNormal = vec4(0.0, 0.0, 1, 0.0); + for(i = 0; i < gl_VerticesIn; i++) { corner = gl_PositionIn[i]; scale = voxelSize[i]; - faceOfVoxel(corner, scale, bottomFace, gl_FrontColorIn[i]); - faceOfVoxel(corner, scale, topFace, gl_FrontColorIn[i]); - faceOfVoxel(corner, scale, rightFace, gl_FrontColorIn[i]); - faceOfVoxel(corner, scale, leftFace, gl_FrontColorIn[i]); - faceOfVoxel(corner, scale, frontFace, gl_FrontColorIn[i]); - faceOfVoxel(corner, scale, backFace, gl_FrontColorIn[i]); + faceOfVoxel(corner, scale, bottomFace, gl_FrontColorIn[i], bottomNormal); + faceOfVoxel(corner, scale, topFace, gl_FrontColorIn[i], topNormal ); + faceOfVoxel(corner, scale, rightFace, gl_FrontColorIn[i], rightNormal ); + faceOfVoxel(corner, scale, leftFace, gl_FrontColorIn[i], leftNormal ); + faceOfVoxel(corner, scale, frontFace, gl_FrontColorIn[i], frontNormal ); + faceOfVoxel(corner, scale, backFace, gl_FrontColorIn[i], backNormal ); } } \ No newline at end of file