Merge pull request #3740 from samcake/temp0

Introduce the input stream stage to the gpu::Batch and apply it for model rendering
This commit is contained in:
AndrewMeadows 2014-11-06 14:14:08 -08:00
commit efd9626c2f
17 changed files with 1038 additions and 272 deletions

View file

@ -81,6 +81,7 @@
#include "renderer/ProgramObject.h"
#include "gpu/Batch.h"
#include "gpu/GLBackend.h"
#include "scripting/AccountScriptingInterface.h"
#include "scripting/AudioDeviceScriptingInterface.h"

View file

@ -12,7 +12,6 @@
#include <QDebug>
//#define ADD_COMMAND(call) _commands.push_back(COMMAND_##call); _commandCalls.push_back(&gpu::Batch::do_##call); _commandOffsets.push_back(_params.size());
#define ADD_COMMAND(call) _commands.push_back(COMMAND_##call); _commandOffsets.push_back(_params.size());
using namespace gpu;
@ -33,6 +32,7 @@ void Batch::clear() {
_commandOffsets.clear();
_params.clear();
_resources.clear();
_buffers.clear();
_data.clear();
}
@ -59,7 +59,7 @@ uint32 Batch::cacheData(uint32 size, const void* data) {
return offset;
}
void Batch::draw(Primitive primitiveType, int nbVertices, int startVertex) {
void Batch::draw(Primitive primitiveType, uint32 nbVertices, uint32 startVertex) {
ADD_COMMAND(draw);
_params.push_back(startVertex);
@ -67,7 +67,7 @@ void Batch::draw(Primitive primitiveType, int nbVertices, int startVertex) {
_params.push_back(primitiveType);
}
void Batch::drawIndexed(Primitive primitiveType, int nbIndices, int startIndex) {
void Batch::drawIndexed(Primitive primitiveType, uint32 nbIndices, uint32 startIndex) {
ADD_COMMAND(drawIndexed);
_params.push_back(startIndex);
@ -75,7 +75,7 @@ void Batch::drawIndexed(Primitive primitiveType, int nbIndices, int startIndex)
_params.push_back(primitiveType);
}
void Batch::drawInstanced(uint32 nbInstances, Primitive primitiveType, int nbVertices, int startVertex, int startInstance) {
void Batch::drawInstanced(uint32 nbInstances, Primitive primitiveType, uint32 nbVertices, uint32 startVertex, uint32 startInstance) {
ADD_COMMAND(drawInstanced);
_params.push_back(startInstance);
@ -85,7 +85,7 @@ void Batch::drawInstanced(uint32 nbInstances, Primitive primitiveType, int nbVer
_params.push_back(nbInstances);
}
void Batch::drawIndexedInstanced(uint32 nbInstances, Primitive primitiveType, int nbIndices, int startIndex, int startInstance) {
void Batch::drawIndexedInstanced(uint32 nbInstances, Primitive primitiveType, uint32 nbIndices, uint32 startIndex, uint32 startInstance) {
ADD_COMMAND(drawIndexedInstanced);
_params.push_back(startInstance);
@ -95,5 +95,36 @@ void Batch::drawIndexedInstanced(uint32 nbInstances, Primitive primitiveType, in
_params.push_back(nbInstances);
}
void Batch::setInputFormat(const Stream::FormatPointer& format) {
ADD_COMMAND(setInputFormat);
_params.push_back(_streamFormats.cache(format));
}
void Batch::setInputStream(Slot startChannel, const BufferStream& stream) {
if (stream.getNumBuffers()) {
const Buffers& buffers = stream.getBuffers();
const Offsets& offsets = stream.getOffsets();
const Offsets& strides = stream.getStrides();
for (int i = 0; i < buffers.size(); i++) {
setInputBuffer(startChannel + i, buffers[i], offsets[i], strides[i]);
}
}
}
void Batch::setInputBuffer(Slot channel, const BufferPointer& buffer, Offset offset, Offset stride) {
ADD_COMMAND(setInputBuffer);
_params.push_back(stride);
_params.push_back(offset);
_params.push_back(_buffers.cache(buffer));
_params.push_back(channel);
}
void Batch::setIndexBuffer(Type type, const BufferPointer& buffer, Offset offset) {
ADD_COMMAND(setIndexBuffer);
_params.push_back(offset);
_params.push_back(_buffers.cache(buffer));
_params.push_back(type);
}

View file

@ -16,6 +16,10 @@
#include <vector>
#include "gpu/Format.h"
#include "gpu/Resource.h"
#include "gpu/Stream.h"
#if defined(NSIGHT_FOUND)
#include "nvToolsExt.h"
class ProfileRange {
@ -35,23 +39,20 @@
namespace gpu {
class Buffer;
class Resource;
typedef int Stamp;
typedef unsigned int uint32;
typedef int int32;
enum Primitive {
PRIMITIVE_POINTS = 0,
PRIMITIVE_LINES,
PRIMITIVE_LINE_STRIP,
PRIMITIVE_TRIANGLES,
PRIMITIVE_TRIANGLE_STRIP,
PRIMITIVE_QUADS,
POINTS = 0,
LINES,
LINE_STRIP,
TRIANGLES,
TRIANGLE_STRIP,
QUADS,
NUM_PRIMITIVES,
};
class Batch {
public:
typedef Stream::Slot Slot;
Batch();
Batch(const Batch& batch);
@ -59,10 +60,18 @@ public:
void clear();
void draw(Primitive primitiveType, int nbVertices, int startVertex = 0);
void drawIndexed(Primitive primitiveType, int nbIndices, int startIndex = 0);
void drawInstanced(uint32 nbInstances, Primitive primitiveType, int nbVertices, int startVertex = 0, int startInstance = 0);
void drawIndexedInstanced(uint32 nbInstances, Primitive primitiveType, int nbIndices, int startIndex = 0, int startInstance = 0);
void draw(Primitive primitiveType, uint32 numVertices, uint32 startVertex = 0);
void drawIndexed(Primitive primitiveType, uint32 nbIndices, uint32 startIndex = 0);
void drawInstanced(uint32 nbInstances, Primitive primitiveType, uint32 nbVertices, uint32 startVertex = 0, uint32 startInstance = 0);
void drawIndexedInstanced(uint32 nbInstances, Primitive primitiveType, uint32 nbIndices, uint32 startIndex = 0, uint32 startInstance = 0);
void setInputFormat(const Stream::FormatPointer& format);
void setInputStream(Slot startChannel, const BufferStream& stream); // not a command, just unroll into a loop of setInputBuffer
void setInputBuffer(Slot channel, const BufferPointer& buffer, Offset offset, Offset stride);
void setIndexBuffer(Type type, const BufferPointer& buffer, Offset offset);
// TODO: As long as we have gl calls explicitely issued from interface
// code, we need to be able to record and batch these calls. THe long
@ -127,13 +136,12 @@ public:
COMMAND_drawIndexed,
COMMAND_drawInstanced,
COMMAND_drawIndexedInstanced,
COMMAND_SET_PIPE_STATE,
COMMAND_SET_VIEWPORT,
COMMAND_SET_FRAMEBUFFER,
COMMAND_SET_RESOURCE,
COMMAND_SET_VERTEX_STREAM,
COMMAND_SET_INDEX_STREAM,
COMMAND_setInputFormat,
COMMAND_setInputBuffer,
COMMAND_setIndexBuffer,
// TODO: As long as we have gl calls explicitely issued from interface
// code, we need to be able to record and batch these calls. THe long
@ -226,21 +234,64 @@ public:
};
typedef std::vector<ResourceCache> Resources;
template <typename T>
class Cache {
public:
typedef QSharedPointer<T> Pointer;
Pointer _pointer;
Cache<T>(const Pointer& pointer) : _pointer(pointer) {}
class Vector {
public:
std::vector< Cache<T> > _pointers;
uint32 cache(const Pointer& pointer) {
uint32 offset = _pointers.size();
_pointers.push_back(Cache<T>(pointer));
return offset;
}
Pointer get(uint32 offset) {
if (offset >= _pointers.size()) {
return Pointer();
}
return (_pointers.data() + offset)->_pointer;
}
void clear() {
_pointers.clear();
}
};
};
typedef Cache<Buffer>::Vector BufferCaches;
typedef Cache<Stream::Format>::Vector StreamFormatCaches;
typedef unsigned char Byte;
typedef std::vector<Byte> Bytes;
uint32 cacheResource(Resource* res);
uint32 cacheResource(const void* pointer);
ResourceCache* editResource(uint32 offset) {
if (offset >= _resources.size())
if (offset >= _resources.size()) {
return 0;
}
return (_resources.data() + offset);
}
template <typename T>
T* editResourcePointer(uint32 offset) {
if (offset >= _resources.size()) {
return 0;
}
return reinterpret_cast<T*>((_resources.data() + offset)->_pointer);
}
uint32 cacheData(uint32 size, const void* data);
Byte* editData(uint32 offset) {
if (offset >= _data.size())
if (offset >= _data.size()) {
return 0;
}
return (_data.data() + offset);
}
@ -248,6 +299,10 @@ public:
CommandOffsets _commandOffsets;
Params _params;
Resources _resources;
BufferCaches _buffers;
StreamFormatCaches _streamFormats;
Bytes _data;
protected:
};

147
interface/src/gpu/Format.h Normal file
View file

@ -0,0 +1,147 @@
//
// Format.h
// interface/src/gpu
//
// Created by Sam Gateau on 10/29/2014.
// Copyright 2014 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#ifndef hifi_gpu_Format_h
#define hifi_gpu_Format_h
#include <assert.h>
#include "InterfaceConfig.h"
namespace gpu {
typedef unsigned int uint32;
typedef int int32;
typedef unsigned short uint16;
typedef short int16;
typedef unsigned char uint8;
typedef char int8;
typedef uint32 Offset;
// Description of a scalar type
enum Type {
FLOAT = 0,
INT32,
UINT32,
HALF,
INT16,
UINT16,
INT8,
UINT8,
NFLOAT,
NINT32,
NUINT32,
NHALF,
NINT16,
NUINT16,
NINT8,
NUINT8,
NUM_TYPES,
};
// Array providing the size in bytes for a given scalar type
static const int TYPE_SIZE[NUM_TYPES] = {
4,
4,
4,
2,
2,
2,
1,
1,
4,
4,
4,
2,
2,
2,
1,
1
};
// Dimension of an Element
enum Dimension {
SCALAR = 0,
VEC2,
VEC3,
VEC4,
MAT3,
MAT4,
NUM_DIMENSIONS,
};
// Count (of scalars) in an Element for a given Dimension
static const int DIMENSION_COUNT[NUM_DIMENSIONS] = {
1,
2,
3,
4,
9,
16
};
// Semantic of an Element
// Provide information on how to use the element
enum Semantic {
RGB = 0,
RGBA,
XYZ,
XYZW,
POS_XYZ,
POS_XYZW,
QUAT,
DIR_XYZ,
UV,
R8,
NUM_SEMANTICS,
};
// Element is a simple 16bit value that contains everything we need to know about an element
// of a buffer, a pixel of a texture, a varying input/output or uniform from a shader pipeline.
// Type and dimension of the element, and semantic
class Element {
public:
Element(Dimension dim, Type type, Semantic sem) :
_semantic(sem),
_dimension(dim),
_type(type)
{}
Element() :
_semantic(R8),
_dimension(SCALAR),
_type(INT8)
{}
Semantic getSemantic() const { return (Semantic)_semantic; }
Dimension getDimension() const { return (Dimension)_dimension; }
uint8 getDimensionCount() const { return DIMENSION_COUNT[(Dimension)_dimension]; }
Type getType() const { return (Type)_type; }
bool isNormalized() const { return (getType() >= NFLOAT); }
uint32 getSize() const { return DIMENSION_COUNT[_dimension] * TYPE_SIZE[_type]; }
protected:
uint8 _semantic;
uint8 _dimension : 4;
uint8 _type : 4;
};
};
#endif

View file

@ -18,6 +18,17 @@ using namespace gpu;
GLBackend::CommandCall GLBackend::_commandCalls[Batch::NUM_COMMANDS] =
{
(&::gpu::GLBackend::do_draw),
(&::gpu::GLBackend::do_drawIndexed),
(&::gpu::GLBackend::do_drawInstanced),
(&::gpu::GLBackend::do_drawIndexedInstanced),
(&::gpu::GLBackend::do_setInputFormat),
(&::gpu::GLBackend::do_setInputBuffer),
(&::gpu::GLBackend::do_setIndexBuffer),
(&::gpu::GLBackend::do_glEnable),
(&::gpu::GLBackend::do_glDisable),
@ -70,8 +81,49 @@ GLBackend::CommandCall GLBackend::_commandCalls[Batch::NUM_COMMANDS] =
(&::gpu::GLBackend::do_glMaterialfv),
};
static const GLenum _primitiveToGLmode[NUM_PRIMITIVES] = {
GL_POINTS,
GL_LINES,
GL_LINE_STRIP,
GL_TRIANGLES,
GL_TRIANGLE_STRIP,
GL_QUADS,
};
GLBackend::GLBackend() {
static const GLenum _elementTypeToGLType[NUM_TYPES]= {
GL_FLOAT,
GL_INT,
GL_UNSIGNED_INT,
GL_HALF_FLOAT,
GL_SHORT,
GL_UNSIGNED_SHORT,
GL_BYTE,
GL_UNSIGNED_BYTE,
GL_FLOAT,
GL_INT,
GL_UNSIGNED_INT,
GL_HALF_FLOAT,
GL_SHORT,
GL_UNSIGNED_SHORT,
GL_BYTE,
GL_UNSIGNED_BYTE
};
GLBackend::GLBackend() :
_inputFormat(0),
_inputAttributeActivation(0),
_needInputFormatUpdate(true),
_inputBuffersState(0),
_inputBuffers(_inputBuffersState.size(), BufferPointer(0)),
_inputBufferOffsets(_inputBuffersState.size(), 0),
_inputBufferStrides(_inputBuffersState.size(), 0),
_indexBuffer(0),
_indexBufferOffset(0)
{
}
@ -87,7 +139,7 @@ void GLBackend::renderBatch(Batch& batch) {
GLBackend backend;
for (int i = 0; i < numCommands; i++) {
CommandCall call = _commandCalls[((*command) - Batch::COMMAND_glEnable)];
CommandCall call = _commandCalls[(*command)];
(backend.*(call))(batch, *offset);
command++;
offset++;
@ -126,24 +178,264 @@ void GLBackend::checkGLError() {
}
}
//#define CHECK_GL_ERROR() ::gpu::GLBackend::checkGLError()
#define CHECK_GL_ERROR()
void GLBackend::do_draw(Batch& batch, uint32 paramOffset) {
updateInput();
Primitive primitiveType = (Primitive)batch._params[paramOffset + 2]._uint;
GLenum mode = _primitiveToGLmode[primitiveType];
uint32 numVertices = batch._params[paramOffset + 1]._uint;
uint32 startVertex = batch._params[paramOffset + 0]._uint;
glDrawArrays(mode, startVertex, numVertices);
CHECK_GL_ERROR();
}
void GLBackend::do_drawIndexed(Batch& batch, uint32 paramOffset) {
updateInput();
Primitive primitiveType = (Primitive)batch._params[paramOffset + 2]._uint;
GLenum mode = _primitiveToGLmode[primitiveType];
uint32 numIndices = batch._params[paramOffset + 1]._uint;
uint32 startIndex = batch._params[paramOffset + 0]._uint;
GLenum glType = _elementTypeToGLType[_indexBufferType];
glDrawElements(mode, numIndices, glType, (GLvoid*)(startIndex + _indexBufferOffset));
CHECK_GL_ERROR();
}
void GLBackend::do_drawInstanced(Batch& batch, uint32 paramOffset) {
CHECK_GL_ERROR();
}
void GLBackend::do_drawIndexedInstanced(Batch& batch, uint32 paramOffset) {
CHECK_GL_ERROR();
}
void GLBackend::do_setInputFormat(Batch& batch, uint32 paramOffset) {
Stream::FormatPointer format = batch._streamFormats.get(batch._params[paramOffset]._uint);
if (format != _inputFormat) {
_inputFormat = format;
_needInputFormatUpdate = true;
}
}
void GLBackend::do_setInputBuffer(Batch& batch, uint32 paramOffset) {
Offset stride = batch._params[paramOffset + 0]._uint;
Offset offset = batch._params[paramOffset + 1]._uint;
BufferPointer buffer = batch._buffers.get(batch._params[paramOffset + 2]._uint);
uint32 channel = batch._params[paramOffset + 3]._uint;
if (channel < getNumInputBuffers()) {
_inputBuffers[channel] = buffer;
_inputBufferOffsets[channel] = offset;
_inputBufferStrides[channel] = stride;
_inputBuffersState.set(channel);
}
}
#define SUPPORT_LEGACY_OPENGL
#if defined(SUPPORT_LEGACY_OPENGL)
static const int NUM_CLASSIC_ATTRIBS = Stream::TANGENT;
static const GLenum attributeSlotToClassicAttribName[NUM_CLASSIC_ATTRIBS] = {
GL_VERTEX_ARRAY,
GL_NORMAL_ARRAY,
GL_COLOR_ARRAY,
GL_TEXTURE_COORD_ARRAY
};
#endif
void GLBackend::updateInput() {
if (_needInputFormatUpdate || _inputBuffersState.any()) {
if (_needInputFormatUpdate) {
InputActivationCache newActivation;
// Check expected activation
if (_inputFormat) {
const Stream::Format::AttributeMap& attributes = _inputFormat->getAttributes();
for (Stream::Format::AttributeMap::const_iterator it = attributes.begin(); it != attributes.end(); it++) {
const Stream::Attribute& attrib = (*it).second;
newActivation.set(attrib._slot);
}
}
// Manage Activation what was and what is expected now
for (int i = 0; i < newActivation.size(); i++) {
bool newState = newActivation[i];
if (newState != _inputAttributeActivation[i]) {
#if defined(SUPPORT_LEGACY_OPENGL)
if (i < NUM_CLASSIC_ATTRIBS) {
if (newState) {
glEnableClientState(attributeSlotToClassicAttribName[i]);
}
else {
glDisableClientState(attributeSlotToClassicAttribName[i]);
}
} else {
#else
{
#endif
if (newState) {
glEnableVertexAttribArray(i);
} else {
glDisableVertexAttribArray(i);
}
}
CHECK_GL_ERROR();
_inputAttributeActivation.flip(i);
}
}
}
// now we need to bind the buffers and assign the attrib pointers
if (_inputFormat) {
const Buffers& buffers = _inputBuffers;
const Offsets& offsets = _inputBufferOffsets;
const Offsets& strides = _inputBufferStrides;
const Stream::Format::AttributeMap& attributes = _inputFormat->getAttributes();
for (Stream::Format::ChannelMap::const_iterator channelIt = _inputFormat->getChannels().begin();
channelIt != _inputFormat->getChannels().end();
channelIt++) {
const Stream::Format::ChannelMap::value_type::second_type& channel = (*channelIt).second;
if ((*channelIt).first < buffers.size()) {
int bufferNum = (*channelIt).first;
if (_inputBuffersState.test(bufferNum) || _needInputFormatUpdate) {
GLuint vbo = gpu::GLBackend::getBufferID((*buffers[bufferNum]));
glBindBuffer(GL_ARRAY_BUFFER, vbo);
CHECK_GL_ERROR();
_inputBuffersState[bufferNum] = false;
for (int i = 0; i < channel._slots.size(); i++) {
const Stream::Attribute& attrib = attributes.at(channel._slots[i]);
GLuint slot = attrib._slot;
GLuint count = attrib._element.getDimensionCount();
GLenum type = _elementTypeToGLType[attrib._element.getType()];
GLuint stride = strides[bufferNum];
GLuint pointer = attrib._offset + offsets[bufferNum];
#if defined(SUPPORT_LEGACY_OPENGL)
if (slot < NUM_CLASSIC_ATTRIBS) {
switch (slot) {
case Stream::POSITION:
glVertexPointer(count, type, stride, (GLvoid*)pointer);
break;
case Stream::NORMAL:
glNormalPointer(type, stride, (GLvoid*)pointer);
break;
case Stream::COLOR:
glColorPointer(count, type, stride, (GLvoid*)pointer);
break;
case Stream::TEXCOORD:
glTexCoordPointer(count, type, stride, (GLvoid*)pointer);
break;
};
} else {
#else
{
#endif
GLboolean isNormalized = attrib._element.isNormalized();
glVertexAttribPointer(slot, count, type, isNormalized, stride, (GLvoid*)pointer);
}
CHECK_GL_ERROR();
}
}
}
}
}
// everything format related should be in sync now
_needInputFormatUpdate = false;
}
/* TODO: Fancy version GL4.4
if (_needInputFormatUpdate) {
InputActivationCache newActivation;
// Assign the vertex format required
if (_inputFormat) {
const StreamFormat::AttributeMap& attributes = _inputFormat->getAttributes();
for (StreamFormat::AttributeMap::const_iterator it = attributes.begin(); it != attributes.end(); it++) {
const StreamFormat::Attribute& attrib = (*it).second;
newActivation.set(attrib._slot);
glVertexAttribFormat(
attrib._slot,
attrib._element.getDimensionCount(),
_elementTypeToGLType[attrib._element.getType()],
attrib._element.isNormalized(),
attrib._stride);
}
CHECK_GL_ERROR();
}
// Manage Activation what was and what is expected now
for (int i = 0; i < newActivation.size(); i++) {
bool newState = newActivation[i];
if (newState != _inputAttributeActivation[i]) {
if (newState) {
glEnableVertexAttribArray(i);
} else {
glDisableVertexAttribArray(i);
}
_inputAttributeActivation.flip(i);
}
}
CHECK_GL_ERROR();
_needInputFormatUpdate = false;
}
if (_needInputStreamUpdate) {
if (_inputStream) {
const Stream::Buffers& buffers = _inputStream->getBuffers();
const Stream::Offsets& offsets = _inputStream->getOffsets();
const Stream::Strides& strides = _inputStream->getStrides();
for (int i = 0; i < buffers.size(); i++) {
GLuint vbo = gpu::GLBackend::getBufferID((*buffers[i]));
glBindVertexBuffer(i, vbo, offsets[i], strides[i]);
}
CHECK_GL_ERROR();
}
_needInputStreamUpdate = false;
}
*/
}
void GLBackend::do_setIndexBuffer(Batch& batch, uint32 paramOffset) {
_indexBufferType = (Type) batch._params[paramOffset + 2]._uint;
BufferPointer indexBuffer = batch._buffers.get(batch._params[paramOffset + 1]._uint);
_indexBufferOffset = batch._params[paramOffset + 0]._uint;
_indexBuffer = indexBuffer;
if (indexBuffer) {
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, getBufferID(*indexBuffer));
} else {
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
}
CHECK_GL_ERROR();
}
// TODO: As long as we have gl calls explicitely issued from interface
// code, we need to be able to record and batch these calls. THe long
// term strategy is to get rid of any GL calls in favor of the HIFI GPU API
//#define ADD_COMMAND(call) _commands.push_back(COMMAND_##call); _commandCalls.push_back(&gpu::Batch::do_##call); _commandOffsets.push_back(_params.size());
#define ADD_COMMAND(call) _commands.push_back(COMMAND_##call); _commandOffsets.push_back(_params.size());
//#define ADD_COMMAND_GL(call) _commands.push_back(COMMAND_##call); _commandCalls.push_back(&gpu::GLBackend::do_##call); _commandOffsets.push_back(_params.size());
#define ADD_COMMAND_GL(call) _commands.push_back(COMMAND_##call); _commandOffsets.push_back(_params.size());
//#define DO_IT_NOW(call, offset) runLastCommand();
#define DO_IT_NOW(call, offset)
//#define CHECK_GL_ERROR() ::gpu::backend::checkGLError()
#define CHECK_GL_ERROR()
void Batch::_glEnable(GLenum cap) {
ADD_COMMAND(glEnable);
ADD_COMMAND_GL(glEnable);
_params.push_back(cap);
@ -155,7 +447,7 @@ void GLBackend::do_glEnable(Batch& batch, uint32 paramOffset) {
}
void Batch::_glDisable(GLenum cap) {
ADD_COMMAND(glDisable);
ADD_COMMAND_GL(glDisable);
_params.push_back(cap);
@ -167,7 +459,7 @@ void GLBackend::do_glDisable(Batch& batch, uint32 paramOffset) {
}
void Batch::_glEnableClientState(GLenum array) {
ADD_COMMAND(glEnableClientState);
ADD_COMMAND_GL(glEnableClientState);
_params.push_back(array);
@ -179,7 +471,7 @@ void GLBackend::do_glEnableClientState(Batch& batch, uint32 paramOffset) {
}
void Batch::_glDisableClientState(GLenum array) {
ADD_COMMAND(glDisableClientState);
ADD_COMMAND_GL(glDisableClientState);
_params.push_back(array);
@ -191,7 +483,7 @@ void GLBackend::do_glDisableClientState(Batch& batch, uint32 paramOffset) {
}
void Batch::_glCullFace(GLenum mode) {
ADD_COMMAND(glCullFace);
ADD_COMMAND_GL(glCullFace);
_params.push_back(mode);
@ -203,7 +495,7 @@ void GLBackend::do_glCullFace(Batch& batch, uint32 paramOffset) {
}
void Batch::_glAlphaFunc(GLenum func, GLclampf ref) {
ADD_COMMAND(glAlphaFunc);
ADD_COMMAND_GL(glAlphaFunc);
_params.push_back(ref);
_params.push_back(func);
@ -218,7 +510,7 @@ void GLBackend::do_glAlphaFunc(Batch& batch, uint32 paramOffset) {
}
void Batch::_glDepthFunc(GLenum func) {
ADD_COMMAND(glDepthFunc);
ADD_COMMAND_GL(glDepthFunc);
_params.push_back(func);
@ -230,7 +522,7 @@ void GLBackend::do_glDepthFunc(Batch& batch, uint32 paramOffset) {
}
void Batch::_glDepthMask(GLboolean flag) {
ADD_COMMAND(glDepthMask);
ADD_COMMAND_GL(glDepthMask);
_params.push_back(flag);
@ -242,7 +534,7 @@ void GLBackend::do_glDepthMask(Batch& batch, uint32 paramOffset) {
}
void Batch::_glDepthRange(GLclampd zNear, GLclampd zFar) {
ADD_COMMAND(glDepthRange);
ADD_COMMAND_GL(glDepthRange);
_params.push_back(zFar);
_params.push_back(zNear);
@ -257,7 +549,7 @@ void GLBackend::do_glDepthRange(Batch& batch, uint32 paramOffset) {
}
void Batch::_glBindBuffer(GLenum target, GLuint buffer) {
ADD_COMMAND(glBindBuffer);
ADD_COMMAND_GL(glBindBuffer);
_params.push_back(buffer);
_params.push_back(target);
@ -272,7 +564,7 @@ void GLBackend::do_glBindBuffer(Batch& batch, uint32 paramOffset) {
}
void Batch::_glBindTexture(GLenum target, GLuint texture) {
ADD_COMMAND(glBindTexture);
ADD_COMMAND_GL(glBindTexture);
_params.push_back(texture);
_params.push_back(target);
@ -287,7 +579,7 @@ void GLBackend::do_glBindTexture(Batch& batch, uint32 paramOffset) {
}
void Batch::_glActiveTexture(GLenum texture) {
ADD_COMMAND(glActiveTexture);
ADD_COMMAND_GL(glActiveTexture);
_params.push_back(texture);
@ -299,7 +591,7 @@ void GLBackend::do_glActiveTexture(Batch& batch, uint32 paramOffset) {
}
void Batch::_glDrawBuffers(GLsizei n, const GLenum* bufs) {
ADD_COMMAND(glDrawBuffers);
ADD_COMMAND_GL(glDrawBuffers);
_params.push_back(cacheData(n * sizeof(GLenum), bufs));
_params.push_back(n);
@ -314,7 +606,7 @@ void GLBackend::do_glDrawBuffers(Batch& batch, uint32 paramOffset) {
}
void Batch::_glUseProgram(GLuint program) {
ADD_COMMAND(glUseProgram);
ADD_COMMAND_GL(glUseProgram);
_params.push_back(program);
@ -326,7 +618,7 @@ void GLBackend::do_glUseProgram(Batch& batch, uint32 paramOffset) {
}
void Batch::_glUniform1f(GLint location, GLfloat v0) {
ADD_COMMAND(glUniform1f);
ADD_COMMAND_GL(glUniform1f);
_params.push_back(v0);
_params.push_back(location);
@ -341,7 +633,7 @@ void GLBackend::do_glUniform1f(Batch& batch, uint32 paramOffset) {
}
void Batch::_glUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) {
ADD_COMMAND(glUniformMatrix4fv);
ADD_COMMAND_GL(glUniformMatrix4fv);
const int MATRIX4_SIZE = 16 * sizeof(float);
_params.push_back(cacheData(count * MATRIX4_SIZE, value));
@ -361,7 +653,7 @@ void GLBackend::do_glUniformMatrix4fv(Batch& batch, uint32 paramOffset) {
}
void Batch::_glMatrixMode(GLenum mode) {
ADD_COMMAND(glMatrixMode);
ADD_COMMAND_GL(glMatrixMode);
_params.push_back(mode);
@ -373,7 +665,7 @@ void GLBackend::do_glMatrixMode(Batch& batch, uint32 paramOffset) {
}
void Batch::_glPushMatrix() {
ADD_COMMAND(glPushMatrix);
ADD_COMMAND_GL(glPushMatrix);
DO_IT_NOW(_glPushMatrix, 0);
}
@ -383,7 +675,7 @@ void GLBackend::do_glPushMatrix(Batch& batch, uint32 paramOffset) {
}
void Batch::_glPopMatrix() {
ADD_COMMAND(glPopMatrix);
ADD_COMMAND_GL(glPopMatrix);
DO_IT_NOW(_glPopMatrix, 0);
}
@ -393,7 +685,7 @@ void GLBackend::do_glPopMatrix(Batch& batch, uint32 paramOffset) {
}
void Batch::_glMultMatrixf(const GLfloat *m) {
ADD_COMMAND(glMultMatrixf);
ADD_COMMAND_GL(glMultMatrixf);
const int MATRIX4_SIZE = 16 * sizeof(float);
_params.push_back(cacheData(MATRIX4_SIZE, m));
@ -406,7 +698,7 @@ void GLBackend::do_glMultMatrixf(Batch& batch, uint32 paramOffset) {
}
void Batch::_glLoadMatrixf(const GLfloat *m) {
ADD_COMMAND(glLoadMatrixf);
ADD_COMMAND_GL(glLoadMatrixf);
const int MATRIX4_SIZE = 16 * sizeof(float);
_params.push_back(cacheData(MATRIX4_SIZE, m));
@ -419,7 +711,7 @@ void GLBackend::do_glLoadMatrixf(Batch& batch, uint32 paramOffset) {
}
void Batch::_glLoadIdentity(void) {
ADD_COMMAND(glLoadIdentity);
ADD_COMMAND_GL(glLoadIdentity);
DO_IT_NOW(_glLoadIdentity, 0);
}
@ -429,7 +721,7 @@ void GLBackend::do_glLoadIdentity(Batch& batch, uint32 paramOffset) {
}
void Batch::_glRotatef(GLfloat angle, GLfloat x, GLfloat y, GLfloat z) {
ADD_COMMAND(glRotatef);
ADD_COMMAND_GL(glRotatef);
_params.push_back(z);
_params.push_back(y);
@ -448,7 +740,7 @@ void GLBackend::do_glRotatef(Batch& batch, uint32 paramOffset) {
}
void Batch::_glScalef(GLfloat x, GLfloat y, GLfloat z) {
ADD_COMMAND(glScalef);
ADD_COMMAND_GL(glScalef);
_params.push_back(z);
_params.push_back(y);
@ -465,7 +757,7 @@ void GLBackend::do_glScalef(Batch& batch, uint32 paramOffset) {
}
void Batch::_glTranslatef(GLfloat x, GLfloat y, GLfloat z) {
ADD_COMMAND(glTranslatef);
ADD_COMMAND_GL(glTranslatef);
_params.push_back(z);
_params.push_back(y);
@ -482,7 +774,7 @@ void GLBackend::do_glTranslatef(Batch& batch, uint32 paramOffset) {
}
void Batch::_glDrawArrays(GLenum mode, GLint first, GLsizei count) {
ADD_COMMAND(glDrawArrays);
ADD_COMMAND_GL(glDrawArrays);
_params.push_back(count);
_params.push_back(first);
@ -499,7 +791,7 @@ void GLBackend::do_glDrawArrays(Batch& batch, uint32 paramOffset) {
}
void Batch::_glDrawRangeElements(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices) {
ADD_COMMAND(glDrawRangeElements);
ADD_COMMAND_GL(glDrawRangeElements);
_params.push_back(cacheResource(indices));
_params.push_back(type);
@ -522,7 +814,7 @@ void GLBackend::do_glDrawRangeElements(Batch& batch, uint32 paramOffset) {
}
void Batch::_glColorPointer(GLint size, GLenum type, GLsizei stride, const void *pointer) {
ADD_COMMAND(glColorPointer);
ADD_COMMAND_GL(glColorPointer);
_params.push_back(cacheResource(pointer));
_params.push_back(stride);
@ -541,7 +833,7 @@ void GLBackend::do_glColorPointer(Batch& batch, uint32 paramOffset) {
}
void Batch::_glNormalPointer(GLenum type, GLsizei stride, const void *pointer) {
ADD_COMMAND(glNormalPointer);
ADD_COMMAND_GL(glNormalPointer);
_params.push_back(cacheResource(pointer));
_params.push_back(stride);
@ -558,7 +850,7 @@ void GLBackend::do_glNormalPointer(Batch& batch, uint32 paramOffset) {
}
void Batch::_glTexCoordPointer(GLint size, GLenum type, GLsizei stride, const void *pointer) {
ADD_COMMAND(glTexCoordPointer);
ADD_COMMAND_GL(glTexCoordPointer);
_params.push_back(cacheResource(pointer));
_params.push_back(stride);
@ -577,7 +869,7 @@ void GLBackend::do_glTexCoordPointer(Batch& batch, uint32 paramOffset) {
}
void Batch::_glVertexPointer(GLint size, GLenum type, GLsizei stride, const void *pointer) {
ADD_COMMAND(glVertexPointer);
ADD_COMMAND_GL(glVertexPointer);
_params.push_back(cacheResource(pointer));
_params.push_back(stride);
@ -597,7 +889,7 @@ void GLBackend::do_glVertexPointer(Batch& batch, uint32 paramOffset) {
void Batch::_glVertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer) {
ADD_COMMAND(glVertexAttribPointer);
ADD_COMMAND_GL(glVertexAttribPointer);
_params.push_back(cacheResource(pointer));
_params.push_back(stride);
@ -620,7 +912,7 @@ void GLBackend::do_glVertexAttribPointer(Batch& batch, uint32 paramOffset) {
}
void Batch::_glEnableVertexAttribArray(GLint location) {
ADD_COMMAND(glEnableVertexAttribArray);
ADD_COMMAND_GL(glEnableVertexAttribArray);
_params.push_back(location);
@ -632,7 +924,7 @@ void GLBackend::do_glEnableVertexAttribArray(Batch& batch, uint32 paramOffset) {
}
void Batch::_glDisableVertexAttribArray(GLint location) {
ADD_COMMAND(glDisableVertexAttribArray);
ADD_COMMAND_GL(glDisableVertexAttribArray);
_params.push_back(location);
@ -644,7 +936,7 @@ void GLBackend::do_glDisableVertexAttribArray(Batch& batch, uint32 paramOffset)
}
void Batch::_glColor4f(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) {
ADD_COMMAND(glColor4f);
ADD_COMMAND_GL(glColor4f);
_params.push_back(alpha);
_params.push_back(blue);
@ -663,7 +955,7 @@ void GLBackend::do_glColor4f(Batch& batch, uint32 paramOffset) {
}
void Batch::_glMaterialf(GLenum face, GLenum pname, GLfloat param) {
ADD_COMMAND(glMaterialf);
ADD_COMMAND_GL(glMaterialf);
_params.push_back(param);
_params.push_back(pname);
@ -680,7 +972,7 @@ void GLBackend::do_glMaterialf(Batch& batch, uint32 paramOffset) {
}
void Batch::_glMaterialfv(GLenum face, GLenum pname, const GLfloat *params) {
ADD_COMMAND(glMaterialfv);
ADD_COMMAND_GL(glMaterialfv);
_params.push_back(cacheData(4 * sizeof(float), params));
_params.push_back(pname);
@ -719,6 +1011,7 @@ void GLBackend::syncGPUObject(const Buffer& buffer) {
if (!object) {
object = new GLBuffer();
glGenBuffers(1, &object->_buffer);
CHECK_GL_ERROR();
Backend::setGPUObject(buffer, object);
}
@ -731,6 +1024,7 @@ void GLBackend::syncGPUObject(const Buffer& buffer) {
object->_stamp = buffer.getSysmem().getStamp();
object->_size = buffer.getSysmem().getSize();
//}
CHECK_GL_ERROR();
}

View file

@ -16,6 +16,8 @@
#include "gpu/Context.h"
#include "gpu/Batch.h"
#include <bitset>
namespace gpu {
@ -43,8 +45,42 @@ public:
static GLuint getBufferID(const Buffer& buffer);
static const int MAX_NUM_ATTRIBUTES = Stream::NUM_INPUT_SLOTS;
static const int MAX_NUM_INPUT_BUFFERS = 16;
uint32 getNumInputBuffers() const { return _inputBuffersState.size(); }
protected:
bool _needInputFormatUpdate;
Stream::FormatPointer _inputFormat;
typedef std::bitset<MAX_NUM_INPUT_BUFFERS> InputBuffersState;
InputBuffersState _inputBuffersState;
Buffers _inputBuffers;
Offsets _inputBufferOffsets;
Offsets _inputBufferStrides;
BufferPointer _indexBuffer;
Offset _indexBufferOffset;
Type _indexBufferType;
typedef std::bitset<MAX_NUM_ATTRIBUTES> InputActivationCache;
InputActivationCache _inputAttributeActivation;
void do_draw(Batch& batch, uint32 paramOffset);
void do_drawIndexed(Batch& batch, uint32 paramOffset);
void do_drawInstanced(Batch& batch, uint32 paramOffset);
void do_drawIndexedInstanced(Batch& batch, uint32 paramOffset);
void updateInput();
void do_setInputFormat(Batch& batch, uint32 paramOffset);
void do_setInputBuffer(Batch& batch, uint32 paramOffset);
void do_setVertexBuffer(Batch& batch, uint32 paramOffset);
void do_setIndexBuffer(Batch& batch, uint32 paramOffset);
// TODO: As long as we have gl calls explicitely issued from interface
// code, we need to be able to record and batch these calls. THe long
// term strategy is to get rid of any GL calls in favor of the HIFI GPU API

View file

@ -120,7 +120,7 @@ Resource::Size Resource::Sysmem::resize(Size size) {
Resource::Size Resource::Sysmem::setData( Size size, const Byte* bytes ) {
if (allocate(size) == size) {
if (bytes) {
if (size && bytes) {
memcpy( _data, bytes, _size );
_stamp++;
}
@ -129,7 +129,7 @@ Resource::Size Resource::Sysmem::setData( Size size, const Byte* bytes ) {
}
Resource::Size Resource::Sysmem::setSubData( Size offset, Size size, const Byte* bytes) {
if (((offset + size) <= getSize()) && bytes) {
if (size && ((offset + size) <= getSize()) && bytes) {
memcpy( _data + offset, bytes, size );
_stamp++;
return size;

View file

@ -14,6 +14,11 @@
#include <assert.h>
#include "InterfaceConfig.h"
#include "gpu/Format.h"
#include <vector>
#include <QSharedPointer>
namespace gpu {
@ -142,6 +147,8 @@ protected:
friend class Backend;
};
typedef QSharedPointer<Buffer> BufferPointer;
typedef std::vector< BufferPointer > Buffers;
};

View file

@ -0,0 +1,48 @@
//
// Stream.cpp
// interface/src/gpu
//
// Created by Sam Gateau on 10/29/2014.
// Copyright 2014 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include "Stream.h"
using namespace gpu;
void Stream::Format::evaluateCache() {
_channels.clear();
_elementTotalSize = 0;
for(AttributeMap::iterator it = _attributes.begin(); it != _attributes.end(); it++) {
Attribute& attrib = (*it).second;
Channel& channel = _channels[attrib._channel];
channel._slots.push_back(attrib._slot);
channel._stride = std::max(channel._stride, attrib.getSize() + attrib._offset);
channel._netSize += attrib.getSize();
_elementTotalSize += attrib.getSize();
}
}
bool Stream::Format::setAttribute(Slot slot, Slot channel, Element element, Offset offset, Frequency frequency) {
_attributes[slot] = Attribute((InputSlot) slot, channel, element, offset, frequency);
evaluateCache();
return true;
}
BufferStream::BufferStream() :
_buffers(),
_offsets(),
_strides()
{}
BufferStream::~BufferStream() {
}
void BufferStream::addBuffer(BufferPointer& buffer, Offset offset, Offset stride) {
_buffers.push_back(buffer);
_offsets.push_back(offset);
_strides.push_back(stride);
}

150
interface/src/gpu/Stream.h Normal file
View file

@ -0,0 +1,150 @@
//
// Stream.h
// interface/src/gpu
//
// Created by Sam Gateau on 10/29/2014.
// Copyright 2014 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#ifndef hifi_gpu_Stream_h
#define hifi_gpu_Stream_h
#include <assert.h>
#include "InterfaceConfig.h"
#include "gpu/Resource.h"
#include "gpu/Format.h"
#include <vector>
#include <map>
namespace gpu {
// Stream namespace class
class Stream {
public:
// Possible input slots identifiers
enum InputSlot {
POSITION = 0,
NORMAL,
COLOR,
TEXCOORD,
TANGENT,
SKIN_CLUSTER_INDEX,
SKIN_CLUSTER_WEIGHT,
NUM_INPUT_SLOTS,
};
typedef uint8 Slot;
// Frequency describer
enum Frequency {
PER_VERTEX = 0,
PER_INSTANCE,
};
// The attribute description
// Every thing that is needed to detail a stream attribute and how to interpret it
class Attribute {
public:
Attribute(Slot slot, Slot channel, Element element, Offset offset = 0, Frequency frequency = PER_VERTEX) :
_slot(slot),
_channel(channel),
_element(element),
_offset(offset),
_frequency(frequency)
{}
Attribute() :
_slot(POSITION),
_channel(0),
_element(),
_offset(0),
_frequency(PER_VERTEX)
{}
Slot _slot; // Logical slot assigned to the attribute
Slot _channel; // index of the channel where to get the data from
Element _element;
Offset _offset;
uint32 _frequency;
// Size of the
uint32 getSize() const { return _element.getSize(); }
};
// Stream Format is describing how to feed a list of attributes from a bunch of stream buffer channels
class Format {
public:
typedef std::map< Slot, Attribute > AttributeMap;
class Channel {
public:
std::vector< Slot > _slots;
std::vector< Offset > _offsets;
Offset _stride;
uint32 _netSize;
Channel() : _stride(0), _netSize(0) {}
};
typedef std::map< Slot, Channel > ChannelMap;
Format() :
_attributes(),
_elementTotalSize(0) {}
~Format() {}
uint32 getNumAttributes() const { return _attributes.size(); }
const AttributeMap& getAttributes() const { return _attributes; }
uint8 getNumChannels() const { return _channels.size(); }
const ChannelMap& getChannels() const { return _channels; }
uint32 getElementTotalSize() const { return _elementTotalSize; }
bool setAttribute(Slot slot, Slot channel, Element element, Offset offset = 0, Frequency frequency = PER_VERTEX);
protected:
AttributeMap _attributes;
ChannelMap _channels;
uint32 _elementTotalSize;
void evaluateCache();
};
typedef QSharedPointer<Format> FormatPointer;
};
typedef std::vector< Offset > Offsets;
// Buffer Stream is a container of N Buffers and their respective Offsets and Srides representing N consecutive channels.
// A Buffer Stream can be assigned to the Batch to set several stream channels in one call
class BufferStream {
public:
typedef Offsets Strides;
BufferStream();
~BufferStream();
void addBuffer(BufferPointer& buffer, Offset offset, Offset stride);
const Buffers& getBuffers() const { return _buffers; }
const Offsets& getOffsets() const { return _offsets; }
const Strides& getStrides() const { return _strides; }
uint8 getNumBuffers() const { return _buffers.size(); }
protected:
Buffers _buffers;
Offsets _offsets;
Strides _strides;
};
typedef QSharedPointer<BufferStream> BufferStreamPointer;
};
#endif

View file

@ -248,9 +248,9 @@ void DeferredLightingEffect::render() {
glLightfv(GL_LIGHT1, GL_DIFFUSE, (const GLfloat*)&light.diffuse);
glLightfv(GL_LIGHT1, GL_SPECULAR, (const GLfloat*)&light.specular);
glLightfv(GL_LIGHT1, GL_POSITION, (const GLfloat*)&light.position);
glLightf(GL_LIGHT1, GL_CONSTANT_ATTENUATION, light.constantAttenuation);
glLightf(GL_LIGHT1, GL_LINEAR_ATTENUATION, light.linearAttenuation);
glLightf(GL_LIGHT1, GL_QUADRATIC_ATTENUATION, light.quadraticAttenuation);
glLightf(GL_LIGHT1, GL_CONSTANT_ATTENUATION, (light.constantAttenuation > 0.f ? light.constantAttenuation : 0.f));
glLightf(GL_LIGHT1, GL_LINEAR_ATTENUATION, (light.linearAttenuation > 0.f ? light.linearAttenuation : 0.f));
glLightf(GL_LIGHT1, GL_QUADRATIC_ATTENUATION, (light.quadraticAttenuation > 0.f ? light.quadraticAttenuation : 0.f));
glPushMatrix();
@ -293,9 +293,9 @@ void DeferredLightingEffect::render() {
glLightfv(GL_LIGHT1, GL_DIFFUSE, (const GLfloat*)&light.diffuse);
glLightfv(GL_LIGHT1, GL_SPECULAR, (const GLfloat*)&light.specular);
glLightfv(GL_LIGHT1, GL_POSITION, (const GLfloat*)&light.position);
glLightf(GL_LIGHT1, GL_CONSTANT_ATTENUATION, light.constantAttenuation);
glLightf(GL_LIGHT1, GL_LINEAR_ATTENUATION, light.linearAttenuation);
glLightf(GL_LIGHT1, GL_QUADRATIC_ATTENUATION, light.quadraticAttenuation);
glLightf(GL_LIGHT1, GL_CONSTANT_ATTENUATION, (light.constantAttenuation > 0.f ? light.constantAttenuation : 0.f));
glLightf(GL_LIGHT1, GL_LINEAR_ATTENUATION, (light.linearAttenuation > 0.f ? light.linearAttenuation : 0.f));
glLightf(GL_LIGHT1, GL_QUADRATIC_ATTENUATION, (light.quadraticAttenuation > 0.f ? light.quadraticAttenuation : 0.f));
glLightfv(GL_LIGHT1, GL_SPOT_DIRECTION, (const GLfloat*)&light.direction);
glLightf(GL_LIGHT1, GL_SPOT_EXPONENT, light.exponent);
glLightf(GL_LIGHT1, GL_SPOT_CUTOFF, glm::degrees(light.cutoff));

View file

@ -840,7 +840,7 @@ void NetworkGeometry::setGeometry(const FBXGeometry& geometry) {
_geometry = geometry;
foreach (const FBXMesh& mesh, _geometry.meshes) {
NetworkMesh networkMesh = { QOpenGLBuffer(QOpenGLBuffer::IndexBuffer), QOpenGLBuffer(QOpenGLBuffer::VertexBuffer) };
NetworkMesh networkMesh;
int totalIndices = 0;
foreach (const FBXMeshPart& part, mesh.parts) {
@ -870,67 +870,103 @@ void NetworkGeometry::setGeometry(const FBXGeometry& geometry) {
totalIndices += (part.quadIndices.size() + part.triangleIndices.size());
}
networkMesh.indexBuffer.create();
networkMesh.indexBuffer.bind();
networkMesh.indexBuffer.setUsagePattern(QOpenGLBuffer::StaticDraw);
networkMesh.indexBuffer.allocate(totalIndices * sizeof(int));
int offset = 0;
foreach (const FBXMeshPart& part, mesh.parts) {
glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, offset, part.quadIndices.size() * sizeof(int),
part.quadIndices.constData());
offset += part.quadIndices.size() * sizeof(int);
glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, offset, part.triangleIndices.size() * sizeof(int),
part.triangleIndices.constData());
offset += part.triangleIndices.size() * sizeof(int);
{
networkMesh._indexBuffer = gpu::BufferPointer(new gpu::Buffer());
networkMesh._indexBuffer->resize(totalIndices * sizeof(int));
int offset = 0;
foreach(const FBXMeshPart& part, mesh.parts) {
networkMesh._indexBuffer->setSubData(offset, part.quadIndices.size() * sizeof(int),
(gpu::Resource::Byte*) part.quadIndices.constData());
offset += part.quadIndices.size() * sizeof(int);
networkMesh._indexBuffer->setSubData(offset, part.triangleIndices.size() * sizeof(int),
(gpu::Resource::Byte*) part.triangleIndices.constData());
offset += part.triangleIndices.size() * sizeof(int);
}
}
networkMesh.indexBuffer.release();
networkMesh.vertexBuffer.create();
networkMesh.vertexBuffer.bind();
networkMesh.vertexBuffer.setUsagePattern(QOpenGLBuffer::StaticDraw);
// if we don't need to do any blending, the positions/normals can be static
if (mesh.blendshapes.isEmpty()) {
int normalsOffset = mesh.vertices.size() * sizeof(glm::vec3);
int tangentsOffset = normalsOffset + mesh.normals.size() * sizeof(glm::vec3);
int colorsOffset = tangentsOffset + mesh.tangents.size() * sizeof(glm::vec3);
int texCoordsOffset = colorsOffset + mesh.colors.size() * sizeof(glm::vec3);
int clusterIndicesOffset = texCoordsOffset + mesh.texCoords.size() * sizeof(glm::vec2);
int clusterWeightsOffset = clusterIndicesOffset + mesh.clusterIndices.size() * sizeof(glm::vec4);
networkMesh.vertexBuffer.allocate(clusterWeightsOffset + mesh.clusterWeights.size() * sizeof(glm::vec4));
networkMesh.vertexBuffer.write(0, mesh.vertices.constData(), mesh.vertices.size() * sizeof(glm::vec3));
networkMesh.vertexBuffer.write(normalsOffset, mesh.normals.constData(), mesh.normals.size() * sizeof(glm::vec3));
networkMesh.vertexBuffer.write(tangentsOffset, mesh.tangents.constData(),
mesh.tangents.size() * sizeof(glm::vec3));
networkMesh.vertexBuffer.write(colorsOffset, mesh.colors.constData(), mesh.colors.size() * sizeof(glm::vec3));
networkMesh.vertexBuffer.write(texCoordsOffset, mesh.texCoords.constData(),
mesh.texCoords.size() * sizeof(glm::vec2));
networkMesh.vertexBuffer.write(clusterIndicesOffset, mesh.clusterIndices.constData(),
mesh.clusterIndices.size() * sizeof(glm::vec4));
networkMesh.vertexBuffer.write(clusterWeightsOffset, mesh.clusterWeights.constData(),
mesh.clusterWeights.size() * sizeof(glm::vec4));
// otherwise, at least the cluster indices/weights can be static
} else {
int colorsOffset = mesh.tangents.size() * sizeof(glm::vec3);
int texCoordsOffset = colorsOffset + mesh.colors.size() * sizeof(glm::vec3);
int clusterIndicesOffset = texCoordsOffset + mesh.texCoords.size() * sizeof(glm::vec2);
int clusterWeightsOffset = clusterIndicesOffset + mesh.clusterIndices.size() * sizeof(glm::vec4);
networkMesh.vertexBuffer.allocate(clusterWeightsOffset + mesh.clusterWeights.size() * sizeof(glm::vec4));
networkMesh.vertexBuffer.write(0, mesh.tangents.constData(), mesh.tangents.size() * sizeof(glm::vec3));
networkMesh.vertexBuffer.write(colorsOffset, mesh.colors.constData(), mesh.colors.size() * sizeof(glm::vec3));
networkMesh.vertexBuffer.write(texCoordsOffset, mesh.texCoords.constData(),
mesh.texCoords.size() * sizeof(glm::vec2));
networkMesh.vertexBuffer.write(clusterIndicesOffset, mesh.clusterIndices.constData(),
mesh.clusterIndices.size() * sizeof(glm::vec4));
networkMesh.vertexBuffer.write(clusterWeightsOffset, mesh.clusterWeights.constData(),
mesh.clusterWeights.size() * sizeof(glm::vec4));
{
networkMesh._vertexBuffer = gpu::BufferPointer(new gpu::Buffer());
// if we don't need to do any blending, the positions/normals can be static
if (mesh.blendshapes.isEmpty()) {
int normalsOffset = mesh.vertices.size() * sizeof(glm::vec3);
int tangentsOffset = normalsOffset + mesh.normals.size() * sizeof(glm::vec3);
int colorsOffset = tangentsOffset + mesh.tangents.size() * sizeof(glm::vec3);
int texCoordsOffset = colorsOffset + mesh.colors.size() * sizeof(glm::vec3);
int clusterIndicesOffset = texCoordsOffset + mesh.texCoords.size() * sizeof(glm::vec2);
int clusterWeightsOffset = clusterIndicesOffset + mesh.clusterIndices.size() * sizeof(glm::vec4);
networkMesh._vertexBuffer->resize(clusterWeightsOffset + mesh.clusterWeights.size() * sizeof(glm::vec4));
//networkMesh.vertexBuffer.allocate(clusterWeightsOffset + mesh.clusterWeights.size() * sizeof(glm::vec4));
networkMesh._vertexBuffer->setSubData(0, mesh.vertices.size() * sizeof(glm::vec3), (gpu::Resource::Byte*) mesh.vertices.constData());
networkMesh._vertexBuffer->setSubData(normalsOffset, mesh.normals.size() * sizeof(glm::vec3), (gpu::Resource::Byte*) mesh.normals.constData());
networkMesh._vertexBuffer->setSubData(tangentsOffset,
mesh.tangents.size() * sizeof(glm::vec3), (gpu::Resource::Byte*) mesh.tangents.constData());
networkMesh._vertexBuffer->setSubData(colorsOffset, mesh.colors.size() * sizeof(glm::vec3), (gpu::Resource::Byte*) mesh.colors.constData());
networkMesh._vertexBuffer->setSubData(texCoordsOffset,
mesh.texCoords.size() * sizeof(glm::vec2), (gpu::Resource::Byte*) mesh.texCoords.constData());
networkMesh._vertexBuffer->setSubData(clusterIndicesOffset,
mesh.clusterIndices.size() * sizeof(glm::vec4), (gpu::Resource::Byte*) mesh.clusterIndices.constData());
networkMesh._vertexBuffer->setSubData(clusterWeightsOffset,
mesh.clusterWeights.size() * sizeof(glm::vec4), (gpu::Resource::Byte*) mesh.clusterWeights.constData());
// otherwise, at least the cluster indices/weights can be static
networkMesh._vertexStream = gpu::BufferStreamPointer(new gpu::BufferStream());
networkMesh._vertexStream->addBuffer(networkMesh._vertexBuffer, 0, sizeof(glm::vec3));
if (mesh.normals.size()) networkMesh._vertexStream->addBuffer(networkMesh._vertexBuffer, normalsOffset, sizeof(glm::vec3));
if (mesh.tangents.size()) networkMesh._vertexStream->addBuffer(networkMesh._vertexBuffer, tangentsOffset, sizeof(glm::vec3));
if (mesh.colors.size()) networkMesh._vertexStream->addBuffer(networkMesh._vertexBuffer, colorsOffset, sizeof(glm::vec3));
if (mesh.texCoords.size()) networkMesh._vertexStream->addBuffer(networkMesh._vertexBuffer, texCoordsOffset, sizeof(glm::vec2));
if (mesh.clusterIndices.size()) networkMesh._vertexStream->addBuffer(networkMesh._vertexBuffer, clusterIndicesOffset, sizeof(glm::vec4));
if (mesh.clusterWeights.size()) networkMesh._vertexStream->addBuffer(networkMesh._vertexBuffer, clusterWeightsOffset, sizeof(glm::vec4));
int channelNum = 0;
networkMesh._vertexFormat = gpu::Stream::FormatPointer(new gpu::Stream::Format());
networkMesh._vertexFormat->setAttribute(gpu::Stream::POSITION, channelNum++, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::POS_XYZ), 0);
if (mesh.normals.size()) networkMesh._vertexFormat->setAttribute(gpu::Stream::NORMAL, channelNum++, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ));
if (mesh.tangents.size()) networkMesh._vertexFormat->setAttribute(gpu::Stream::TANGENT, channelNum++, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ));
if (mesh.colors.size()) networkMesh._vertexFormat->setAttribute(gpu::Stream::COLOR, channelNum++, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::RGB));
if (mesh.texCoords.size()) networkMesh._vertexFormat->setAttribute(gpu::Stream::TEXCOORD, channelNum++, gpu::Element(gpu::VEC2, gpu::FLOAT, gpu::UV));
if (mesh.clusterIndices.size()) networkMesh._vertexFormat->setAttribute(gpu::Stream::SKIN_CLUSTER_INDEX, channelNum++, gpu::Element(gpu::VEC4, gpu::NFLOAT, gpu::XYZW));
if (mesh.clusterWeights.size()) networkMesh._vertexFormat->setAttribute(gpu::Stream::SKIN_CLUSTER_WEIGHT, channelNum++, gpu::Element(gpu::VEC4, gpu::NFLOAT, gpu::XYZW));
}
else {
int colorsOffset = mesh.tangents.size() * sizeof(glm::vec3);
int texCoordsOffset = colorsOffset + mesh.colors.size() * sizeof(glm::vec3);
int clusterIndicesOffset = texCoordsOffset + mesh.texCoords.size() * sizeof(glm::vec2);
int clusterWeightsOffset = clusterIndicesOffset + mesh.clusterIndices.size() * sizeof(glm::vec4);
networkMesh._vertexBuffer->resize(clusterWeightsOffset + mesh.clusterWeights.size() * sizeof(glm::vec4));
networkMesh._vertexBuffer->setSubData(0, mesh.tangents.size() * sizeof(glm::vec3), (gpu::Resource::Byte*) mesh.tangents.constData());
networkMesh._vertexBuffer->setSubData(colorsOffset, mesh.colors.size() * sizeof(glm::vec3), (gpu::Resource::Byte*) mesh.colors.constData());
networkMesh._vertexBuffer->setSubData(texCoordsOffset,
mesh.texCoords.size() * sizeof(glm::vec2), (gpu::Resource::Byte*) mesh.texCoords.constData());
networkMesh._vertexBuffer->setSubData(clusterIndicesOffset,
mesh.clusterIndices.size() * sizeof(glm::vec4), (gpu::Resource::Byte*) mesh.clusterIndices.constData());
networkMesh._vertexBuffer->setSubData(clusterWeightsOffset,
mesh.clusterWeights.size() * sizeof(glm::vec4), (gpu::Resource::Byte*) mesh.clusterWeights.constData());
networkMesh._vertexStream = gpu::BufferStreamPointer(new gpu::BufferStream());
if (mesh.tangents.size()) networkMesh._vertexStream->addBuffer(networkMesh._vertexBuffer, 0, sizeof(glm::vec3));
if (mesh.colors.size()) networkMesh._vertexStream->addBuffer(networkMesh._vertexBuffer, colorsOffset, sizeof(glm::vec3));
if (mesh.texCoords.size()) networkMesh._vertexStream->addBuffer(networkMesh._vertexBuffer, texCoordsOffset, sizeof(glm::vec2));
if (mesh.clusterIndices.size()) networkMesh._vertexStream->addBuffer(networkMesh._vertexBuffer, clusterIndicesOffset, sizeof(glm::vec4));
if (mesh.clusterWeights.size()) networkMesh._vertexStream->addBuffer(networkMesh._vertexBuffer, clusterWeightsOffset, sizeof(glm::vec4));
int channelNum = 0;
networkMesh._vertexFormat = gpu::Stream::FormatPointer(new gpu::Stream::Format());
networkMesh._vertexFormat->setAttribute(gpu::Stream::POSITION, channelNum++, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::POS_XYZ));
if (mesh.normals.size()) networkMesh._vertexFormat->setAttribute(gpu::Stream::NORMAL, channelNum++, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ));
if (mesh.tangents.size()) networkMesh._vertexFormat->setAttribute(gpu::Stream::TANGENT, channelNum++, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ));
if (mesh.colors.size()) networkMesh._vertexFormat->setAttribute(gpu::Stream::COLOR, channelNum++, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::RGB));
if (mesh.texCoords.size()) networkMesh._vertexFormat->setAttribute(gpu::Stream::TEXCOORD, channelNum++, gpu::Element(gpu::VEC2, gpu::FLOAT, gpu::UV));
if (mesh.clusterIndices.size()) networkMesh._vertexFormat->setAttribute(gpu::Stream::SKIN_CLUSTER_INDEX, channelNum++, gpu::Element(gpu::VEC4, gpu::NFLOAT, gpu::XYZW));
if (mesh.clusterWeights.size()) networkMesh._vertexFormat->setAttribute(gpu::Stream::SKIN_CLUSTER_WEIGHT, channelNum++, gpu::Element(gpu::VEC4, gpu::NFLOAT, gpu::XYZW));
}
}
networkMesh.vertexBuffer.release();
_meshes.append(networkMesh);
}

View file

@ -24,6 +24,8 @@
#include <AnimationCache.h>
#include "gpu/Stream.h"
class Model;
class NetworkGeometry;
class NetworkMesh;
@ -155,9 +157,12 @@ public:
/// The state associated with a single mesh.
class NetworkMesh {
public:
QOpenGLBuffer indexBuffer;
QOpenGLBuffer vertexBuffer;
gpu::BufferPointer _indexBuffer;
gpu::BufferPointer _vertexBuffer;
gpu::BufferStreamPointer _vertexStream;
gpu::Stream::FormatPointer _vertexFormat;
QVector<NetworkMeshPart> parts;

View file

@ -137,6 +137,10 @@ void Model::initProgram(ProgramObject& program, Model::Locations& locations, int
glBindAttribLocation(program.programId(), gpu::Stream::TANGENT, "tangent");
glLinkProgram(program.programId());
locations.tangent = program.attributeLocation("tangent");
locations.alphaThreshold = program.uniformLocation("alphaThreshold");
@ -171,7 +175,13 @@ void Model::initSkinProgram(ProgramObject& program, Model::SkinLocations& locati
#endif
// HACK: Assign explicitely the attribute channel to avoid a bug on Yosemite
glBindAttribLocation(program.programId(), gpu::Stream::SKIN_CLUSTER_INDEX, "clusterIndices");
glBindAttribLocation(program.programId(), gpu::Stream::SKIN_CLUSTER_WEIGHT, "clusterWeights");
glLinkProgram(program.programId());
program.bind();
@ -395,19 +405,15 @@ bool Model::updateGeometry() {
MeshState state;
state.clusterMatrices.resize(mesh.clusters.size());
_meshStates.append(state);
QOpenGLBuffer buffer;
gpu::BufferPointer buffer(new gpu::Buffer());
if (!mesh.blendshapes.isEmpty()) {
buffer.setUsagePattern(QOpenGLBuffer::DynamicDraw);
buffer.create();
buffer.bind();
buffer.allocate((mesh.vertices.size() + mesh.normals.size()) * sizeof(glm::vec3));
buffer.write(0, mesh.vertices.constData(), mesh.vertices.size() * sizeof(glm::vec3));
buffer.write(mesh.vertices.size() * sizeof(glm::vec3), mesh.normals.constData(),
mesh.normals.size() * sizeof(glm::vec3));
buffer.release();
buffer->resize((mesh.vertices.size() + mesh.normals.size()) * sizeof(glm::vec3));
buffer->setSubData(0, mesh.vertices.size() * sizeof(glm::vec3), (gpu::Resource::Byte*) mesh.vertices.constData());
buffer->setSubData(mesh.vertices.size() * sizeof(glm::vec3),
mesh.normals.size() * sizeof(glm::vec3), (gpu::Resource::Byte*) mesh.normals.constData());
}
_blendedVertexBuffers.append(buffer);
_blendedVertexBuffers.push_back(buffer);
}
foreach (const FBXAttachment& attachment, fbxGeometry.attachments) {
Model* model = new Model(this);
@ -516,6 +522,7 @@ void Model::recalcuateMeshBoxes() {
bool Model::render(float alpha, RenderMode mode, RenderArgs* args) {
PROFILE_RANGE(__FUNCTION__);
// render the attachments
foreach (Model* attachment, _attachments) {
attachment->render(alpha, mode);
@ -549,8 +556,6 @@ bool Model::render(float alpha, RenderMode mode, RenderArgs* args) {
// Let's introduce a gpu::Batch to capture all the calls to the graphics api
gpu::Batch batch;
GLBATCH(glEnableClientState)(GL_VERTEX_ARRAY);
GLBATCH(glEnableClientState)(GL_NORMAL_ARRAY);
GLBATCH(glDisable)(GL_COLOR_MATERIAL);
@ -665,6 +670,10 @@ bool Model::render(float alpha, RenderMode mode, RenderArgs* args) {
GLBATCH(glDisableClientState)(GL_NORMAL_ARRAY);
GLBATCH(glDisableClientState)(GL_VERTEX_ARRAY);
GLBATCH(glDisableClientState)(GL_TEXTURE_COORD_ARRAY);
GLBATCH(glDisableClientState)(GL_COLOR_ARRAY);
GLBATCH(glDisableVertexAttribArray)(gpu::Stream::TANGENT);
GLBATCH(glDisableVertexAttribArray)(gpu::Stream::SKIN_CLUSTER_INDEX);
GLBATCH(glDisableVertexAttribArray)(gpu::Stream::SKIN_CLUSTER_WEIGHT);
// bind with 0 to switch back to normal operation
GLBATCH(glBindBuffer)(GL_ARRAY_BUFFER, 0);
@ -1391,7 +1400,7 @@ bool Model::maybeStartBlender() {
void Model::setBlendedVertices(int blendNumber, const QWeakPointer<NetworkGeometry>& geometry,
const QVector<glm::vec3>& vertices, const QVector<glm::vec3>& normals) {
if (_geometry != geometry || _blendedVertexBuffers.isEmpty() || blendNumber < _appliedBlendNumber) {
if (_geometry != geometry || _blendedVertexBuffers.empty() || blendNumber < _appliedBlendNumber) {
return;
}
_appliedBlendNumber = blendNumber;
@ -1402,12 +1411,12 @@ void Model::setBlendedVertices(int blendNumber, const QWeakPointer<NetworkGeomet
if (mesh.blendshapes.isEmpty()) {
continue;
}
QOpenGLBuffer& buffer = _blendedVertexBuffers[i];
buffer.bind();
buffer.write(0, vertices.constData() + index, mesh.vertices.size() * sizeof(glm::vec3));
buffer.write(mesh.vertices.size() * sizeof(glm::vec3), normals.constData() + index,
mesh.normals.size() * sizeof(glm::vec3));
buffer.release();
gpu::BufferPointer& buffer = _blendedVertexBuffers[i];
buffer->setSubData(0, mesh.vertices.size() * sizeof(glm::vec3), (gpu::Resource::Byte*) vertices.constData() + index*sizeof(glm::vec3));
buffer->setSubData(mesh.vertices.size() * sizeof(glm::vec3),
mesh.normals.size() * sizeof(glm::vec3), (gpu::Resource::Byte*) normals.constData() + index*sizeof(glm::vec3));
index += mesh.vertices.size();
}
}
@ -1791,11 +1800,8 @@ int Model::renderMeshes(gpu::Batch& batch, RenderMode mode, bool translucent, fl
activeProgram->link();
}
GLBATCH(glUseProgram)(activeProgram->programId());
// activeProgram->setUniformValue(activeLocations->alphaThreshold, alphaThreshold);
GLBATCH(glUniform1f)(activeLocations->alphaThreshold, alphaThreshold);
// i is the "index" from the original networkMeshes QVector...
foreach (int i, list) {
@ -1811,9 +1817,7 @@ int Model::renderMeshes(gpu::Batch& batch, RenderMode mode, bool translucent, fl
const NetworkMesh& networkMesh = networkMeshes.at(i);
const FBXMesh& mesh = geometry.meshes.at(i);
//const_cast<QOpenGLBuffer&>(networkMesh.indexBuffer).bind();
GLBATCH(glBindBuffer)(GL_ELEMENT_ARRAY_BUFFER, const_cast<QOpenGLBuffer&>(networkMesh.indexBuffer).bufferId());
batch.setIndexBuffer(gpu::UINT32, (networkMesh._indexBuffer), 0);
int vertexCount = mesh.vertices.size();
if (vertexCount == 0) {
// sanity check
@ -1846,9 +1850,6 @@ int Model::renderMeshes(gpu::Batch& batch, RenderMode mode, bool translucent, fl
continue; // skip this mesh
}
}
//const_cast<QOpenGLBuffer&>(networkMesh.vertexBuffer).bind();
GLBATCH(glBindBuffer)(GL_ARRAY_BUFFER, const_cast<QOpenGLBuffer&>(networkMesh.vertexBuffer).bufferId());
GLBATCH(glPushMatrix)();
//Application::getInstance()->loadTranslatedViewMatrix(_translation);
@ -1861,59 +1862,24 @@ int Model::renderMeshes(gpu::Batch& batch, RenderMode mode, bool translucent, fl
if (state.clusterMatrices.size() > 1) {
GLBATCH(glUniformMatrix4fv)(skinLocations->clusterMatrices, state.clusterMatrices.size(), false,
(const float*)state.clusterMatrices.constData());
int offset = (mesh.tangents.size() + mesh.colors.size()) * sizeof(glm::vec3) +
mesh.texCoords.size() * sizeof(glm::vec2) +
(mesh.blendshapes.isEmpty() ? vertexCount * 2 * sizeof(glm::vec3) : 0);
//skinProgram->setAttributeBuffer(skinLocations->clusterIndices, GL_FLOAT, offset, 4);
GLBATCH(glVertexAttribPointer)(skinLocations->clusterIndices, 4, GL_FLOAT, GL_TRUE, 0,
reinterpret_cast<const void*>(offset));
//skinProgram->setAttributeBuffer(skinLocations->clusterWeights, GL_FLOAT,
// offset + vertexCount * sizeof(glm::vec4), 4);
GLBATCH(glVertexAttribPointer)(skinLocations->clusterWeights, 4, GL_FLOAT, GL_TRUE, 0, (const void*) (offset + vertexCount * sizeof(glm::vec4)));
//skinProgram->enableAttributeArray(skinLocations->clusterIndices);
GLBATCH(glEnableVertexAttribArray)(skinLocations->clusterIndices);
//skinProgram->enableAttributeArray(skinLocations->clusterWeights);
GLBATCH(glEnableVertexAttribArray)(skinLocations->clusterWeights);
} else {
GLBATCH(glMultMatrixf)((const GLfloat*)&state.clusterMatrices[0]);
}
if (mesh.blendshapes.isEmpty()) {
if (!(mesh.tangents.isEmpty() || mode == SHADOW_RENDER_MODE)) {
//activeProgram->setAttributeBuffer(activeLocations->tangent, GL_FLOAT, vertexCount * 2 * sizeof(glm::vec3), 3);
GLBATCH(glVertexAttribPointer)(activeLocations->tangent, 3, GL_FLOAT, GL_TRUE, 0, (const void*)(vertexCount * 2 * sizeof(glm::vec3)));
//activeProgram->enableAttributeArray(activeLocations->tangent);
GLBATCH(glEnableVertexAttribArray)(activeLocations->tangent);
}
GLBATCH(glColorPointer)(3, GL_FLOAT, 0, (void*)(vertexCount * 2 * sizeof(glm::vec3) +
mesh.tangents.size() * sizeof(glm::vec3)));
GLBATCH(glTexCoordPointer)(2, GL_FLOAT, 0, (void*)(vertexCount * 2 * sizeof(glm::vec3) +
(mesh.tangents.size() + mesh.colors.size()) * sizeof(glm::vec3)));
batch.setInputFormat(networkMesh._vertexFormat);
batch.setInputStream(0, *networkMesh._vertexStream);
} else {
if (!(mesh.tangents.isEmpty() || mode == SHADOW_RENDER_MODE)) {
//activeProgram->setAttributeBuffer(activeLocations->tangent, GL_FLOAT, 0, 3);
GLBATCH(glVertexAttribPointer)(activeLocations->tangent, 3, GL_FLOAT, GL_TRUE, 0, 0);
//activeProgram->enableAttributeArray(activeLocations->tangent);
GLBATCH(glEnableVertexAttribArray)(activeLocations->tangent);
}
GLBATCH(glColorPointer)(3, GL_FLOAT, 0, (void*)(mesh.tangents.size() * sizeof(glm::vec3)));
GLBATCH(glTexCoordPointer)(2, GL_FLOAT, 0, (void*)((mesh.tangents.size() + mesh.colors.size()) * sizeof(glm::vec3)));
// _blendedVertexBuffers[i].bind();
GLBATCH(glBindBuffer)(GL_ARRAY_BUFFER, _blendedVertexBuffers[i].bufferId());
batch.setInputFormat(networkMesh._vertexFormat);
batch.setInputBuffer(0, _blendedVertexBuffers[i], 0, sizeof(glm::vec3));
batch.setInputBuffer(1, _blendedVertexBuffers[i], vertexCount * sizeof(glm::vec3), sizeof(glm::vec3));
batch.setInputStream(2, *networkMesh._vertexStream);
}
GLBATCH(glVertexPointer)(3, GL_FLOAT, 0, 0);
GLBATCH(glNormalPointer)(GL_FLOAT, 0, (void*)(vertexCount * sizeof(glm::vec3)));
if (!mesh.colors.isEmpty()) {
GLBATCH(glEnableClientState)(GL_COLOR_ARRAY);
} else {
if (mesh.colors.isEmpty()) {
GLBATCH(glColor4f)(1.0f, 1.0f, 1.0f, 1.0f);
}
if (!mesh.texCoords.isEmpty()) {
GLBATCH(glEnableClientState)(GL_TEXTURE_COORD_ARRAY);
}
qint64 offset = 0;
for (int j = 0; j < networkMesh.parts.size(); j++) {
const NetworkMeshPart& networkPart = networkMesh.parts.at(j);
@ -1980,13 +1946,12 @@ int Model::renderMeshes(gpu::Batch& batch, RenderMode mode, bool translucent, fl
meshPartsRendered++;
if (part.quadIndices.size() > 0) {
GLBATCH(glDrawRangeElements)(GL_QUADS, 0, vertexCount - 1, part.quadIndices.size(), GL_UNSIGNED_INT, (void*)offset);
batch.drawIndexed(gpu::QUADS, part.quadIndices.size(), offset);
offset += part.quadIndices.size() * sizeof(int);
}
if (part.triangleIndices.size() > 0) {
GLBATCH(glDrawRangeElements)(GL_TRIANGLES, 0, vertexCount - 1, part.triangleIndices.size(),
GL_UNSIGNED_INT, (void*)offset);
batch.drawIndexed(gpu::TRIANGLES, part.triangleIndices.size(), offset);
offset += part.triangleIndices.size() * sizeof(int);
}
@ -1997,39 +1962,23 @@ int Model::renderMeshes(gpu::Batch& batch, RenderMode mode, bool translucent, fl
args->_quadsRendered += part.quadIndices.size() / INDICES_PER_QUAD;
}
}
if (!mesh.colors.isEmpty()) {
GLBATCH(glDisableClientState)(GL_COLOR_ARRAY);
}
if (!mesh.texCoords.isEmpty()) {
GLBATCH(glDisableClientState)(GL_TEXTURE_COORD_ARRAY);
}
if (!(mesh.tangents.isEmpty() || mode == SHADOW_RENDER_MODE)) {
GLBATCH(glActiveTexture)(GL_TEXTURE1);
GLBATCH(glBindTexture)(GL_TEXTURE_2D, 0);
GLBATCH(glActiveTexture)(GL_TEXTURE0);
// activeProgram->disableAttributeArray(activeLocations->tangent);
GLBATCH(glDisableVertexAttribArray)(activeLocations->tangent);
}
if (specularTextureUnit) {
GLBATCH(glActiveTexture)(specularTextureUnit);
GLBATCH(glBindTexture)(GL_TEXTURE_2D, 0);
GLBATCH(glActiveTexture)(GL_TEXTURE0);
}
if (state.clusterMatrices.size() > 1) {
// skinProgram->disableAttributeArray(skinLocations->clusterIndices);
GLBATCH(glDisableVertexAttribArray)(skinLocations->clusterIndices);
// skinProgram->disableAttributeArray(skinLocations->clusterWeights);
GLBATCH(glDisableVertexAttribArray)(skinLocations->clusterWeights);
}
GLBATCH(glPopMatrix)();
}
//activeProgram->release();
GLBATCH(glUseProgram)(0);
return meshPartsRendered;

View file

@ -40,6 +40,8 @@ namespace gpu {
class Batch;
}
#include "gpu/Stream.h"
/// A generic 3D model displaying geometry loaded from a URL.
class Model : public QObject, public PhysicsEntity {
Q_OBJECT
@ -279,8 +281,8 @@ private:
QVector<float> _blendshapeCoefficients;
QUrl _url;
QVector<QOpenGLBuffer> _blendedVertexBuffers;
gpu::Buffers _blendedVertexBuffers;
QVector<QVector<QSharedPointer<Texture> > > _dilatedTextures;

View file

@ -25,6 +25,7 @@
#include <glm/gtc/matrix_transform.hpp>
#include "gpu/GLBackend.h"
#include "gpu/Stream.h"
// the width/height of the cached glyph textures
@ -132,12 +133,12 @@ int TextRenderer::draw(int x, int y, const char* str) {
gpu::Buffer::Size offset = sizeof(vertexBuffer) * _numGlyphsBatched;
gpu::Buffer::Size colorOffset = sizeof(colorBuffer) * _numGlyphsBatched;
if ((offset + sizeof(vertexBuffer)) > _glyphsBuffer.getSize()) {
_glyphsBuffer.append(sizeof(vertexBuffer), (gpu::Buffer::Byte*) vertexBuffer);
_glyphsColorBuffer.append(sizeof(colorBuffer), (gpu::Buffer::Byte*) colorBuffer);
if ((offset + sizeof(vertexBuffer)) > _glyphsBuffer->getSize()) {
_glyphsBuffer->append(sizeof(vertexBuffer), (gpu::Buffer::Byte*) vertexBuffer);
_glyphsColorBuffer->append(sizeof(colorBuffer), (gpu::Buffer::Byte*) colorBuffer);
} else {
_glyphsBuffer.setSubData(offset, sizeof(vertexBuffer), (gpu::Buffer::Byte*) vertexBuffer);
_glyphsColorBuffer.setSubData(colorOffset, sizeof(colorBuffer), (gpu::Buffer::Byte*) colorBuffer);
_glyphsBuffer->setSubData(offset, sizeof(vertexBuffer), (gpu::Buffer::Byte*) vertexBuffer);
_glyphsColorBuffer->setSubData(colorOffset, sizeof(colorBuffer), (gpu::Buffer::Byte*) colorBuffer);
}
_numGlyphsBatched++;
@ -178,9 +179,22 @@ TextRenderer::TextRenderer(const Properties& properties) :
_y(IMAGE_SIZE),
_rowHeight(0),
_color(properties.color),
_glyphsBuffer(),
_numGlyphsBatched(0)
_glyphsBuffer(new gpu::Buffer()),
_glyphsColorBuffer(new gpu::Buffer()),
_numGlyphsBatched(0),
_glyphsStreamFormat(new gpu::Stream::Format()),
_glyphsStream(new gpu::BufferStream())
{
_glyphsStreamFormat->setAttribute(gpu::Stream::POSITION, 0, gpu::Element(gpu::VEC2, gpu::FLOAT, gpu::POS_XYZ), 0);
const int NUM_POS_COORDS = 2;
const int VERTEX_TEXCOORD_OFFSET = NUM_POS_COORDS * sizeof(float);
_glyphsStreamFormat->setAttribute(gpu::Stream::TEXCOORD, 0, gpu::Element(gpu::VEC2, gpu::FLOAT, gpu::UV), VERTEX_TEXCOORD_OFFSET);
_glyphsStreamFormat->setAttribute(gpu::Stream::COLOR, 1, gpu::Element(gpu::VEC4, gpu::UINT8, gpu::RGBA));
_glyphsStream->addBuffer(_glyphsBuffer, 0, _glyphsStreamFormat->getChannels().at(0)._stride);
_glyphsStream->addBuffer(_glyphsColorBuffer, 0, _glyphsStreamFormat->getChannels().at(1)._stride);
_font.setKerning(false);
}
@ -295,30 +309,17 @@ void TextRenderer::drawBatch() {
glLoadIdentity();
*/
gpu::Batch batch;
glEnable(GL_TEXTURE_2D);
// TODO: Apply the correct font atlas texture, for now only one texture per TextRenderer so it should be good
glBindTexture(GL_TEXTURE_2D, _currentTextureID);
GLuint vbo = gpu::GLBackend::getBufferID(_glyphsBuffer);
GLuint colorvbo = gpu::GLBackend::getBufferID(_glyphsColorBuffer);
batch.setInputFormat(_glyphsStreamFormat);
batch.setInputStream(0, *_glyphsStream);
batch.draw(gpu::QUADS, _numGlyphsBatched * 4, 0);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
const int NUM_POS_COORDS = 2;
const int NUM_TEX_COORDS = 2;
const int VERTEX_STRIDE = (NUM_POS_COORDS + NUM_TEX_COORDS) * sizeof(float);
const int VERTEX_TEXCOORD_OFFSET = NUM_POS_COORDS * sizeof(float);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glVertexPointer(2, GL_FLOAT, VERTEX_STRIDE, 0);
glTexCoordPointer(2, GL_FLOAT, VERTEX_STRIDE, (GLvoid*) VERTEX_TEXCOORD_OFFSET );
glBindBuffer(GL_ARRAY_BUFFER, colorvbo);
glColorPointer(4, GL_UNSIGNED_BYTE, 0, (GLvoid*) 0 );
glDrawArrays(GL_QUADS, 0, _numGlyphsBatched * 4);
gpu::GLBackend::renderBatch(batch);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);

View file

@ -20,6 +20,8 @@
#include <QVector>
#include "gpu/Resource.h"
#include "gpu/Stream.h"
#include "InterfaceConfig.h"
@ -105,8 +107,10 @@ private:
QColor _color;
// Graphics Buffer containing the current accumulated glyphs to render
gpu::Buffer _glyphsBuffer;
gpu::Buffer _glyphsColorBuffer;
gpu::BufferPointer _glyphsBuffer;
gpu::BufferPointer _glyphsColorBuffer;
gpu::Stream::FormatPointer _glyphsStreamFormat;
gpu::BufferStreamPointer _glyphsStream;
int _numGlyphsBatched;
static QHash<Properties, TextRenderer*> _instances;