More work on avatar voxels.

This commit is contained in:
Andrzej Kapolka 2013-06-01 15:06:29 -07:00
parent 7425b39237
commit 6c975f9c6f
6 changed files with 121 additions and 19 deletions

View file

@ -0,0 +1,34 @@
#version 120
//
// skin_voxels.vert
// vertex shader
//
// Created by Andrzej Kapolka on 5/31/13.
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
//
const int MAX_BONES = 32;
const int INDICES_PER_VERTEX = 4;
uniform mat4 boneMatrices[MAX_BONES];
attribute vec4 boneIndices;
attribute vec4 boneWeights;
void main(void) {
vec4 position = vec4(0.0, 0.0, 0.0, 0.0);
vec4 normal = vec4(0.0, 0.0, 0.0, 0.0);
for (int i = 0; i < INDICES_PER_VERTEX; i++) {
mat4 boneMatrix = boneMatrices[int(boneIndices[i])];
float boneWeight = boneWeights[i];
position += boneMatrix * gl_Vertex * boneWeight;
normal += boneMatrix * vec4(gl_Normal, 0.0) * boneWeight;
}
position = gl_ModelViewProjectionMatrix * position;
normal = normalize(gl_ModelViewMatrix * normal);
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 = position;
}

View file

@ -88,7 +88,8 @@ Avatar::Avatar(Agent* owningAgent) :
_mouseRayDirection(0.0f, 0.0f, 0.0f),
_interactingOther(NULL),
_cumulativeMouseYaw(0.0f),
_isMouseTurningRight(false)
_isMouseTurningRight(false),
_voxels(this)
{
// give the pointer to our head to inherited _headData variable from AvatarData

View file

@ -8,13 +8,18 @@
#include <cstring>
#include "AvatarVoxelSystem.h"
#include "renderer/ProgramObject.h"
const float AVATAR_TREE_SCALE = 1.0f;
const int MAX_VOXELS_PER_AVATAR = 2000;
const int BONE_INDEX_ELEMENTS_PER_VOXEL = 4 * VERTICES_PER_VOXEL;
const int BONE_WEIGHT_ELEMENTS_PER_VOXEL = 4 * VERTICES_PER_VOXEL;
const int BONE_INDEX_ELEMENTS_PER_VERTEX = 4;
const int BONE_INDEX_ELEMENTS_PER_VOXEL = BONE_INDEX_ELEMENTS_PER_VERTEX * VERTICES_PER_VOXEL;
const int BONE_WEIGHT_ELEMENTS_PER_VERTEX = 4;
const int BONE_WEIGHT_ELEMENTS_PER_VOXEL = BONE_WEIGHT_ELEMENTS_PER_VERTEX * VERTICES_PER_VOXEL;
AvatarVoxelSystem::AvatarVoxelSystem() : VoxelSystem(AVATAR_TREE_SCALE, MAX_VOXELS_PER_AVATAR) {
AvatarVoxelSystem::AvatarVoxelSystem(Avatar* avatar) :
VoxelSystem(AVATAR_TREE_SCALE, MAX_VOXELS_PER_AVATAR),
_avatar(avatar) {
}
AvatarVoxelSystem::~AvatarVoxelSystem() {
@ -24,6 +29,11 @@ AvatarVoxelSystem::~AvatarVoxelSystem() {
delete[] _writeBoneWeightsArray;
}
ProgramObject* AvatarVoxelSystem::_skinProgram = 0;
int AvatarVoxelSystem::_boneMatricesLocation;
int AvatarVoxelSystem::_boneIndicesLocation;
int AvatarVoxelSystem::_boneWeightsLocation;
void AvatarVoxelSystem::init() {
VoxelSystem::init();
@ -43,6 +53,18 @@ void AvatarVoxelSystem::init() {
glGenBuffers(1, &_vboBoneWeightsID);
glBindBuffer(GL_ARRAY_BUFFER, _vboBoneWeightsID);
glBufferData(GL_ARRAY_BUFFER, BONE_WEIGHT_ELEMENTS_PER_VOXEL * sizeof(GLfloat) * _maxVoxels, NULL, GL_DYNAMIC_DRAW);
// load our skin program if this is the first avatar system to initialize
if (_skinProgram != 0) {
return;
}
_skinProgram = new ProgramObject();
_skinProgram->addShaderFromSourceFile(QGLShader::Vertex, "resources/shaders/skin_voxels.vert");
_skinProgram->link();
_boneMatricesLocation = _skinProgram->uniformLocation("boneMatrices");
_boneIndicesLocation = _skinProgram->attributeLocation("boneIndices");
_boneWeightsLocation = _skinProgram->attributeLocation("boneWeights");
}
void AvatarVoxelSystem::render(bool texture) {
@ -53,11 +75,15 @@ void AvatarVoxelSystem::updateNodeInArrays(glBufferIndex nodeIndex, const glm::v
float voxelScale, const nodeColor& color) {
VoxelSystem::updateNodeInArrays(nodeIndex, startVertex, voxelScale, color);
for (int j = 0; j < BONE_INDEX_ELEMENTS_PER_VOXEL; j++) {
GLubyte* writeBoneIndicesAt = _writeBoneIndicesArray + (nodeIndex * BONE_INDEX_ELEMENTS_PER_VOXEL);
GLfloat* writeBoneWeightsAt = _writeBoneWeightsArray + (nodeIndex * BONE_WEIGHT_ELEMENTS_PER_VOXEL);
*(writeBoneIndicesAt + j) = 0;
*(writeBoneWeightsAt + j) = 0.0f;
GLubyte* writeBoneIndicesAt = _writeBoneIndicesArray + (nodeIndex * BONE_INDEX_ELEMENTS_PER_VOXEL);
GLfloat* writeBoneWeightsAt = _writeBoneWeightsArray + (nodeIndex * BONE_WEIGHT_ELEMENTS_PER_VOXEL);
for (int i = 0; i < VERTICES_PER_VOXEL; i++) {
GLubyte boneIndices[] = { 0, 0, 0, 0};
glm::vec4 boneWeights = glm::vec4(1.0f, 0.0f, 0.0f, 0.0f);
for (int j = 0; j < BONE_INDEX_ELEMENTS_PER_VERTEX; j++) {
*(writeBoneIndicesAt + i * BONE_INDEX_ELEMENTS_PER_VERTEX + j) = boneIndices[j];
*(writeBoneWeightsAt + i * BONE_WEIGHT_ELEMENTS_PER_VERTEX + j) = boneWeights[j];
}
}
}
@ -95,3 +121,25 @@ void AvatarVoxelSystem::updateVBOSegment(glBufferIndex segmentStart, glBufferInd
glBufferSubData(GL_ARRAY_BUFFER, segmentStartAt, segmentSizeBytes, readBoneWeightsFrom);
}
void AvatarVoxelSystem::bindProgram(bool texture) {
_skinProgram->bind();
QMatrix4x4 boneMatrices[1];
_skinProgram->setUniformValueArray(_boneMatricesLocation, boneMatrices, sizeof(boneMatrices) / sizeof(boneMatrices[0]));
glBindBuffer(GL_ARRAY_BUFFER, _vboBoneIndicesID);
_skinProgram->setAttributeBuffer(_boneIndicesLocation, GL_UNSIGNED_BYTE, 0, BONE_INDEX_ELEMENTS_PER_VERTEX);
_skinProgram->enableAttributeArray(_boneIndicesLocation);
glBindBuffer(GL_ARRAY_BUFFER, _vboBoneWeightsID);
_skinProgram->setAttributeBuffer(_boneWeightsLocation, GL_FLOAT, 0, BONE_WEIGHT_ELEMENTS_PER_VERTEX);
_skinProgram->enableAttributeArray(_boneWeightsLocation);
}
void AvatarVoxelSystem::releaseProgram(bool texture) {
_skinProgram->release();
_skinProgram->disableAttributeArray(_boneIndicesLocation);
_skinProgram->disableAttributeArray(_boneWeightsLocation);
}

View file

@ -11,10 +11,12 @@
#include "VoxelSystem.h"
class Avatar;
class AvatarVoxelSystem : public VoxelSystem {
public:
AvatarVoxelSystem();
AvatarVoxelSystem(Avatar* avatar);
virtual ~AvatarVoxelSystem();
virtual void init();
@ -26,9 +28,13 @@ protected:
float voxelScale, const nodeColor& color);
virtual void copyWrittenDataSegmentToReadArrays(glBufferIndex segmentStart, glBufferIndex segmentEnd);
virtual void updateVBOSegment(glBufferIndex segmentStart, glBufferIndex segmentEnd);
virtual void bindProgram(bool texture);
virtual void releaseProgram(bool texture);
private:
Avatar* _avatar;
GLubyte* _readBoneIndicesArray;
GLfloat* _readBoneWeightsArray;
GLubyte* _writeBoneIndicesArray;
@ -37,7 +43,10 @@ private:
GLuint _vboBoneIndicesID;
GLuint _vboBoneWeightsID;
ProgramObject* _skinProgram;
static ProgramObject* _skinProgram;
static int _boneMatricesLocation;
static int _boneIndicesLocation;
static int _boneWeightsLocation;
};
#endif /* defined(__interface__AvatarVoxelSystem__) */

View file

@ -625,10 +625,7 @@ void VoxelSystem::render(bool texture) {
glBindBuffer(GL_ARRAY_BUFFER, _vboColorsID);
glColorPointer(3, GL_UNSIGNED_BYTE, 0, 0);
if (texture) {
_perlinModulateProgram->bind();
glBindTexture(GL_TEXTURE_2D, _permutationNormalTextureID);
}
bindProgram(texture);
// for performance, disable blending and enable backface culling
glDisable(GL_BLEND);
@ -643,10 +640,7 @@ void VoxelSystem::render(bool texture) {
glEnable(GL_BLEND);
glDisable(GL_CULL_FACE);
if (texture) {
_perlinModulateProgram->release();
glBindTexture(GL_TEXTURE_2D, 0);
}
releaseProgram(texture);
// deactivate vertex and color arrays after drawing
glDisableClientState(GL_VERTEX_ARRAY);
@ -663,6 +657,20 @@ void VoxelSystem::render(bool texture) {
pthread_mutex_unlock(&_bufferWriteLock);
}
void VoxelSystem::bindProgram(bool texture) {
if (texture) {
_perlinModulateProgram->bind();
glBindTexture(GL_TEXTURE_2D, _permutationNormalTextureID);
}
}
void VoxelSystem::releaseProgram(bool texture) {
if (texture) {
_perlinModulateProgram->release();
glBindTexture(GL_TEXTURE_2D, 0);
}
}
int VoxelSystem::_nodeCount = 0;
void VoxelSystem::killLocalVoxels() {

View file

@ -87,6 +87,8 @@ protected:
float voxelScale, const nodeColor& color);
virtual void copyWrittenDataSegmentToReadArrays(glBufferIndex segmentStart, glBufferIndex segmentEnd);
virtual void updateVBOSegment(glBufferIndex segmentStart, glBufferIndex segmentEnd);
virtual void bindProgram(bool texture);
virtual void releaseProgram(bool texture);
private:
// disallow copying of VoxelSystem objects