BGE: Some as of yet unmerged work I did in the Swiss branch. These changes include:
* Cleaning up the conversion code to avoid a per-face material conversion. Materials are now stored in buckets and only converted if a new material is found. This replaces some of Campbell's earlier work on the subject. His work wasn't as thorough, but it was much safer for a release. * Shaders are only compiled for LibLoaded materials once. Before they could be compiled twice, which could really slow things down. * Refactoring the rasterizer code to use a strategy design pattern to handle different geometry rendering methods such as immediate mode, vertex arrays and vertex buffer objects. VBOs are added, but they will be disabled in a following commit since they are still slower than vertex arrays with display lists. However, VBOs are still useful for mobile, so it's good to keep them around. * Better multi-uv support. The BGE should now be able to handle more than two UV layers, which should help it better match the viewport.
This commit is contained in:
@@ -43,6 +43,10 @@
|
||||
#include "MT_CmMatrix4x4.h"
|
||||
#include "RAS_IRenderTools.h" // rendering text
|
||||
|
||||
#include "RAS_StorageIM.h"
|
||||
#include "RAS_StorageVA.h"
|
||||
#include "RAS_StorageVBO.h"
|
||||
|
||||
#include "GPU_draw.h"
|
||||
#include "GPU_material.h"
|
||||
#include "GPU_extensions.h"
|
||||
@@ -74,7 +78,7 @@ static GLuint right_eye_vinterlace_mask[32];
|
||||
*/
|
||||
static GLuint hinterlace_mask[33];
|
||||
|
||||
RAS_OpenGLRasterizer::RAS_OpenGLRasterizer(RAS_ICanvas* canvas)
|
||||
RAS_OpenGLRasterizer::RAS_OpenGLRasterizer(RAS_ICanvas* canvas, int storage)
|
||||
:RAS_IRasterizer(canvas),
|
||||
m_2DCanvas(canvas),
|
||||
m_fogenabled(false),
|
||||
@@ -93,7 +97,8 @@ RAS_OpenGLRasterizer::RAS_OpenGLRasterizer(RAS_ICanvas* canvas)
|
||||
m_attrib_num(0),
|
||||
//m_last_alphablend(GPU_BLEND_SOLID),
|
||||
m_last_frontface(true),
|
||||
m_materialCachingInfo(0)
|
||||
m_materialCachingInfo(0),
|
||||
m_storage_type(storage)
|
||||
{
|
||||
m_viewmatrix.setIdentity();
|
||||
m_viewinvmatrix.setIdentity();
|
||||
@@ -107,6 +112,24 @@ RAS_OpenGLRasterizer::RAS_OpenGLRasterizer(RAS_ICanvas* canvas)
|
||||
hinterlace_mask[32] = 0;
|
||||
|
||||
m_prevafvalue = GPU_get_anisotropic();
|
||||
|
||||
if (m_storage_type == RAS_VBO /*|| m_storage_type == RAS_AUTO_STORAGE && GLEW_ARB_vertex_buffer_object*/)
|
||||
{
|
||||
m_storage = new RAS_StorageVBO(&m_texco_num, m_texco, &m_attrib_num, m_attrib);
|
||||
m_failsafe_storage = new RAS_StorageIM(&m_texco_num, m_texco, &m_attrib_num, m_attrib);
|
||||
m_storage_type = RAS_VBO;
|
||||
}
|
||||
else if (m_storage_type == RAS_VA || m_storage_type == RAS_AUTO_STORAGE && GLEW_VERSION_1_1)
|
||||
{
|
||||
m_storage = new RAS_StorageVA(&m_texco_num, m_texco, &m_attrib_num, m_attrib);
|
||||
m_failsafe_storage = new RAS_StorageIM(&m_texco_num, m_texco, &m_attrib_num, m_attrib);
|
||||
m_storage_type = RAS_VA;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_storage = m_failsafe_storage = new RAS_StorageIM(&m_texco_num, m_texco, &m_attrib_num, m_attrib);
|
||||
m_storage_type = RAS_IMMEDIATE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -115,10 +138,16 @@ RAS_OpenGLRasterizer::~RAS_OpenGLRasterizer()
|
||||
{
|
||||
// Restore the previous AF value
|
||||
GPU_set_anisotropic(m_prevafvalue);
|
||||
if (m_failsafe_storage && m_failsafe_storage != m_storage)
|
||||
delete m_failsafe_storage;
|
||||
|
||||
if (m_storage)
|
||||
delete m_storage;
|
||||
}
|
||||
|
||||
bool RAS_OpenGLRasterizer::Init()
|
||||
{
|
||||
bool storage_init;
|
||||
GPU_state_init();
|
||||
|
||||
|
||||
@@ -146,7 +175,9 @@ bool RAS_OpenGLRasterizer::Init()
|
||||
|
||||
glShadeModel(GL_SMOOTH);
|
||||
|
||||
return true;
|
||||
storage_init = m_storage->Init();
|
||||
|
||||
return true && storage_init;
|
||||
}
|
||||
|
||||
|
||||
@@ -267,6 +298,8 @@ bool RAS_OpenGLRasterizer::SetMaterial(const RAS_IPolyMaterial& mat)
|
||||
void RAS_OpenGLRasterizer::Exit()
|
||||
{
|
||||
|
||||
m_storage->Exit();
|
||||
|
||||
glEnable(GL_CULL_FACE);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glClearDepth(1.0);
|
||||
@@ -289,7 +322,7 @@ void RAS_OpenGLRasterizer::Exit()
|
||||
bool RAS_OpenGLRasterizer::BeginFrame(int drawingmode, double time)
|
||||
{
|
||||
m_time = time;
|
||||
m_drawingmode = drawingmode;
|
||||
SetDrawingMode(drawingmode);
|
||||
|
||||
// Blender camera routine destroys the settings
|
||||
if (m_drawingmode < KX_SOLID)
|
||||
@@ -328,6 +361,8 @@ void RAS_OpenGLRasterizer::SetDrawingMode(int drawingmode)
|
||||
|
||||
if (m_drawingmode == KX_WIREFRAME)
|
||||
glDisable(GL_CULL_FACE);
|
||||
|
||||
m_storage->SetDrawingMode(drawingmode);
|
||||
}
|
||||
|
||||
int RAS_OpenGLRasterizer::GetDrawingMode()
|
||||
@@ -666,7 +701,7 @@ void RAS_OpenGLRasterizer::IndexPrimitives_3DText(RAS_MeshSlot& ms,
|
||||
glattrib = -1;
|
||||
if (GLEW_ARB_vertex_program)
|
||||
for (unit=0; unit<m_attrib_num; unit++)
|
||||
if (m_attrib[unit] == RAS_TEXCO_UV1)
|
||||
if (m_attrib[unit] == RAS_TEXCO_UV)
|
||||
glattrib = unit;
|
||||
|
||||
rendertools->RenderText(polymat->GetDrawingMode(), polymat,
|
||||
@@ -708,257 +743,20 @@ void RAS_OpenGLRasterizer::SetAttrib(TexCoGen coords, int unit)
|
||||
m_attrib[unit] = coords;
|
||||
}
|
||||
|
||||
void RAS_OpenGLRasterizer::TexCoord(const RAS_TexVert &tv)
|
||||
{
|
||||
int unit;
|
||||
|
||||
if (GLEW_ARB_multitexture) {
|
||||
for (unit=0; unit<m_texco_num; unit++) {
|
||||
if (tv.getFlag() & RAS_TexVert::SECOND_UV && (int)tv.getUnit() == unit) {
|
||||
glMultiTexCoord2fvARB(GL_TEXTURE0_ARB+unit, tv.getUV2());
|
||||
continue;
|
||||
}
|
||||
switch (m_texco[unit]) {
|
||||
case RAS_TEXCO_ORCO:
|
||||
case RAS_TEXCO_GLOB:
|
||||
glMultiTexCoord3fvARB(GL_TEXTURE0_ARB+unit, tv.getXYZ());
|
||||
break;
|
||||
case RAS_TEXCO_UV1:
|
||||
glMultiTexCoord2fvARB(GL_TEXTURE0_ARB+unit, tv.getUV1());
|
||||
break;
|
||||
case RAS_TEXCO_NORM:
|
||||
glMultiTexCoord3fvARB(GL_TEXTURE0_ARB+unit, tv.getNormal());
|
||||
break;
|
||||
case RAS_TEXTANGENT:
|
||||
glMultiTexCoord4fvARB(GL_TEXTURE0_ARB+unit, tv.getTangent());
|
||||
break;
|
||||
case RAS_TEXCO_UV2:
|
||||
glMultiTexCoord2fvARB(GL_TEXTURE0_ARB+unit, tv.getUV2());
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (GLEW_ARB_vertex_program) {
|
||||
for (unit=0; unit<m_attrib_num; unit++) {
|
||||
switch (m_attrib[unit]) {
|
||||
case RAS_TEXCO_ORCO:
|
||||
case RAS_TEXCO_GLOB:
|
||||
glVertexAttrib3fvARB(unit, tv.getXYZ());
|
||||
break;
|
||||
case RAS_TEXCO_UV1:
|
||||
glVertexAttrib2fvARB(unit, tv.getUV1());
|
||||
break;
|
||||
case RAS_TEXCO_NORM:
|
||||
glVertexAttrib3fvARB(unit, tv.getNormal());
|
||||
break;
|
||||
case RAS_TEXTANGENT:
|
||||
glVertexAttrib4fvARB(unit, tv.getTangent());
|
||||
break;
|
||||
case RAS_TEXCO_UV2:
|
||||
glVertexAttrib2fvARB(unit, tv.getUV2());
|
||||
break;
|
||||
case RAS_TEXCO_VCOL:
|
||||
glVertexAttrib4ubvARB(unit, tv.getRGBA());
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void RAS_OpenGLRasterizer::IndexPrimitives(RAS_MeshSlot& ms)
|
||||
{
|
||||
IndexPrimitivesInternal(ms, false);
|
||||
if (ms.m_pDerivedMesh)
|
||||
m_failsafe_storage->IndexPrimitives(ms);
|
||||
else
|
||||
m_storage->IndexPrimitives(ms);
|
||||
}
|
||||
|
||||
void RAS_OpenGLRasterizer::IndexPrimitivesMulti(RAS_MeshSlot& ms)
|
||||
{
|
||||
IndexPrimitivesInternal(ms, true);
|
||||
}
|
||||
|
||||
static bool current_wireframe;
|
||||
static RAS_MaterialBucket *current_bucket;
|
||||
static RAS_IPolyMaterial *current_polymat;
|
||||
static RAS_MeshSlot *current_ms;
|
||||
static RAS_MeshObject *current_mesh;
|
||||
static int current_blmat_nr;
|
||||
static GPUVertexAttribs current_gpu_attribs;
|
||||
static Image *current_image;
|
||||
static int CheckMaterialDM(int matnr, void *attribs)
|
||||
{
|
||||
// only draw the current material
|
||||
if (matnr != current_blmat_nr)
|
||||
return 0;
|
||||
GPUVertexAttribs *gattribs = (GPUVertexAttribs *)attribs;
|
||||
if (gattribs)
|
||||
memcpy(gattribs, ¤t_gpu_attribs, sizeof(GPUVertexAttribs));
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
static int CheckTexfaceDM(void *mcol, int index)
|
||||
{
|
||||
|
||||
// index is the original face index, retrieve the polygon
|
||||
RAS_Polygon* polygon = (index >= 0 && index < current_mesh->NumPolygons()) ?
|
||||
current_mesh->GetPolygon(index) : NULL;
|
||||
if (polygon && polygon->GetMaterial() == current_bucket) {
|
||||
// must handle color.
|
||||
if (current_wireframe)
|
||||
return 2;
|
||||
if (current_ms->m_bObjectColor) {
|
||||
MT_Vector4& rgba = current_ms->m_RGBAcolor;
|
||||
glColor4d(rgba[0], rgba[1], rgba[2], rgba[3]);
|
||||
// don't use mcol
|
||||
return 2;
|
||||
}
|
||||
if (!mcol) {
|
||||
// we have to set the color from the material
|
||||
unsigned char rgba[4];
|
||||
current_polymat->GetMaterialRGBAColor(rgba);
|
||||
glColor4ubv((const GLubyte *)rgba);
|
||||
return 2;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
*/
|
||||
|
||||
static DMDrawOption CheckTexDM(MTFace *tface, int has_mcol, int matnr)
|
||||
{
|
||||
|
||||
// index is the original face index, retrieve the polygon
|
||||
if (matnr == current_blmat_nr &&
|
||||
(tface == NULL || tface->tpage == current_image)) {
|
||||
// must handle color.
|
||||
if (current_wireframe)
|
||||
return DM_DRAW_OPTION_NO_MCOL;
|
||||
if (current_ms->m_bObjectColor) {
|
||||
MT_Vector4& rgba = current_ms->m_RGBAcolor;
|
||||
glColor4d(rgba[0], rgba[1], rgba[2], rgba[3]);
|
||||
// don't use mcol
|
||||
return DM_DRAW_OPTION_NO_MCOL;
|
||||
}
|
||||
if (!has_mcol) {
|
||||
// we have to set the color from the material
|
||||
unsigned char rgba[4];
|
||||
current_polymat->GetMaterialRGBAColor(rgba);
|
||||
glColor4ubv((const GLubyte *)rgba);
|
||||
return DM_DRAW_OPTION_NO_MCOL;
|
||||
}
|
||||
return DM_DRAW_OPTION_NORMAL;
|
||||
}
|
||||
return DM_DRAW_OPTION_SKIP;
|
||||
}
|
||||
|
||||
void RAS_OpenGLRasterizer::IndexPrimitivesInternal(RAS_MeshSlot& ms, bool multi)
|
||||
{
|
||||
bool obcolor = ms.m_bObjectColor;
|
||||
bool wireframe = m_drawingmode <= KX_WIREFRAME;
|
||||
MT_Vector4& rgba = ms.m_RGBAcolor;
|
||||
RAS_MeshSlot::iterator it;
|
||||
|
||||
if (ms.m_pDerivedMesh) {
|
||||
// mesh data is in derived mesh,
|
||||
current_bucket = ms.m_bucket;
|
||||
current_polymat = current_bucket->GetPolyMaterial();
|
||||
current_ms = &ms;
|
||||
current_mesh = ms.m_mesh;
|
||||
current_wireframe = wireframe;
|
||||
// MCol *mcol = (MCol*)ms.m_pDerivedMesh->getFaceDataArray(ms.m_pDerivedMesh, CD_MCOL); /* UNUSED */
|
||||
|
||||
// handle two-side
|
||||
if (current_polymat->GetDrawingMode() & RAS_IRasterizer::KX_BACKCULL)
|
||||
this->SetCullFace(true);
|
||||
else
|
||||
this->SetCullFace(false);
|
||||
|
||||
if (current_polymat->GetFlag() & RAS_BLENDERGLSL) {
|
||||
// GetMaterialIndex return the original mface material index,
|
||||
// increment by 1 to match what derived mesh is doing
|
||||
current_blmat_nr = current_polymat->GetMaterialIndex()+1;
|
||||
// For GLSL we need to retrieve the GPU material attribute
|
||||
Material* blmat = current_polymat->GetBlenderMaterial();
|
||||
Scene* blscene = current_polymat->GetBlenderScene();
|
||||
if (!wireframe && blscene && blmat)
|
||||
GPU_material_vertex_attributes(GPU_material_from_blender(blscene, blmat), ¤t_gpu_attribs);
|
||||
else
|
||||
memset(¤t_gpu_attribs, 0, sizeof(current_gpu_attribs));
|
||||
// DM draw can mess up blending mode, restore at the end
|
||||
int current_blend_mode = GPU_get_material_alpha_blend();
|
||||
ms.m_pDerivedMesh->drawFacesGLSL(ms.m_pDerivedMesh, CheckMaterialDM);
|
||||
GPU_set_material_alpha_blend(current_blend_mode);
|
||||
}
|
||||
else {
|
||||
//ms.m_pDerivedMesh->drawMappedFacesTex(ms.m_pDerivedMesh, CheckTexfaceDM, mcol);
|
||||
current_blmat_nr = current_polymat->GetMaterialIndex();
|
||||
current_image = current_polymat->GetBlenderImage();
|
||||
ms.m_pDerivedMesh->drawFacesTex(ms.m_pDerivedMesh, CheckTexDM, NULL, NULL);
|
||||
}
|
||||
return;
|
||||
}
|
||||
// iterate over display arrays, each containing an index + vertex array
|
||||
for (ms.begin(it); !ms.end(it); ms.next(it)) {
|
||||
RAS_TexVert *vertex;
|
||||
size_t i, j, numvert;
|
||||
|
||||
numvert = it.array->m_type;
|
||||
|
||||
if (it.array->m_type == RAS_DisplayArray::LINE) {
|
||||
// line drawing
|
||||
glBegin(GL_LINES);
|
||||
|
||||
for (i=0; i<it.totindex; i+=2)
|
||||
{
|
||||
vertex = &it.vertex[it.index[i]];
|
||||
glVertex3fv(vertex->getXYZ());
|
||||
|
||||
vertex = &it.vertex[it.index[i+1]];
|
||||
glVertex3fv(vertex->getXYZ());
|
||||
}
|
||||
|
||||
glEnd();
|
||||
}
|
||||
else {
|
||||
// triangle and quad drawing
|
||||
if (it.array->m_type == RAS_DisplayArray::TRIANGLE)
|
||||
glBegin(GL_TRIANGLES);
|
||||
else
|
||||
glBegin(GL_QUADS);
|
||||
|
||||
for (i=0; i<it.totindex; i+=numvert)
|
||||
{
|
||||
if (obcolor)
|
||||
glColor4d(rgba[0], rgba[1], rgba[2], rgba[3]);
|
||||
|
||||
for (j=0; j<numvert; j++) {
|
||||
vertex = &it.vertex[it.index[i+j]];
|
||||
|
||||
if (!wireframe) {
|
||||
if (!obcolor)
|
||||
glColor4ubv((const GLubyte *)(vertex->getRGBA()));
|
||||
|
||||
glNormal3fv(vertex->getNormal());
|
||||
|
||||
if (multi)
|
||||
TexCoord(*vertex);
|
||||
else
|
||||
glTexCoord2fv(vertex->getUV1());
|
||||
}
|
||||
|
||||
glVertex3fv(vertex->getXYZ());
|
||||
}
|
||||
}
|
||||
|
||||
glEnd();
|
||||
}
|
||||
}
|
||||
if (ms.m_pDerivedMesh)
|
||||
m_failsafe_storage->IndexPrimitivesMulti(ms);
|
||||
else
|
||||
m_storage->IndexPrimitivesMulti(ms);
|
||||
}
|
||||
|
||||
void RAS_OpenGLRasterizer::SetProjectionMatrix(MT_CmMatrix4x4 &mat)
|
||||
|
Reference in New Issue
Block a user