mirror of
https://github.com/HifiExperiments/overte.git
synced 2025-07-25 01:53:37 +02:00
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:
commit
efd9626c2f
17 changed files with 1038 additions and 272 deletions
|
@ -81,6 +81,7 @@
|
|||
|
||||
#include "renderer/ProgramObject.h"
|
||||
#include "gpu/Batch.h"
|
||||
#include "gpu/GLBackend.h"
|
||||
|
||||
#include "scripting/AccountScriptingInterface.h"
|
||||
#include "scripting/AudioDeviceScriptingInterface.h"
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
147
interface/src/gpu/Format.h
Normal 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
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
||||
|
|
48
interface/src/gpu/Stream.cpp
Normal file
48
interface/src/gpu/Stream.cpp
Normal 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
150
interface/src/gpu/Stream.h
Normal 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
|
|
@ -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));
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue