2012-11-01 15:19:01 +00:00
// Copyright (c) 2012- PPSSPP Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
2012-11-04 22:01:49 +00:00
// the Free Software Foundation, version 2.0 or later versions.
2012-11-01 15:19:01 +00:00
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official git repository and contact information can be found at
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
2012-11-05 13:09:49 +00:00
# if defined(ANDROID) || defined(BLACKBERRY)
2012-11-01 15:19:01 +00:00
# include <GLES2/gl2.h>
# include <GLES2/gl2ext.h>
# else
# include <GL/glew.h>
# if defined(__APPLE__)
# include <OpenGL/gl.h>
# else
# include <GL/gl.h>
# endif
# endif
# include "../../Core/MemMap.h"
# include "../../Core/Host.h"
# include "../../Core/System.h"
# include "../Math3D.h"
# include "../GPUState.h"
# include "../ge_constants.h"
# include "TextureCache.h"
# include "TransformPipeline.h"
# include "VertexDecoder.h"
# include "ShaderManager.h"
GLuint glprim [ 8 ] =
{
GL_POINTS ,
GL_LINES ,
GL_LINE_STRIP ,
GL_TRIANGLES ,
GL_TRIANGLE_STRIP ,
GL_TRIANGLE_FAN ,
2012-11-09 16:51:45 +00:00
GL_TRIANGLES , // With OpenGL ES we have to expand sprites into triangles, tripling the data instead of doubling. sigh. OpenGL ES, Y U NO SUPPORT GL_QUADS?
2012-11-01 15:19:01 +00:00
} ;
DecodedVertex decoded [ 65536 ] ;
TransformedVertex transformed [ 65536 ] ;
2012-11-16 15:19:37 +00:00
TransformedVertex transformedExpanded [ 65536 ] ;
2012-11-01 15:19:01 +00:00
uint16_t indexBuffer [ 65536 ] ; // Unused
2012-11-09 16:51:45 +00:00
// TODO: This should really return 2 colors, one for specular and one for diffuse.
2012-11-16 14:16:14 +00:00
// Convenient way to do precomputation to save the parts of the lighting calculation
// that's common between the many vertices of a draw call.
class Lighter {
public :
Lighter ( ) ;
void Light ( float colorOut0 [ 4 ] , float colorOut1 [ 4 ] , const float colorIn [ 4 ] , Vec3 pos , Vec3 normal , float dots [ 4 ] ) ;
private :
bool disabled_ ;
Color4 globalAmbient ;
Color4 materialEmissive ;
Color4 materialAmbient ;
Color4 materialDiffuse ;
Color4 materialSpecular ;
float specCoef_ ;
Vec3 viewer_ ;
bool doShadeMapping_ ;
int materialUpdate_ ;
} ;
2012-11-01 15:19:01 +00:00
2012-11-16 14:16:14 +00:00
Lighter : : Lighter ( ) {
disabled_ = false ;
doShadeMapping_ = ( gstate . texmapmode & 0x3 ) = = 2 ;
if ( ! doShadeMapping_ & & ! ( gstate . lightEnable [ 0 ] & 1 ) & & ! ( gstate . lightEnable [ 1 ] & 1 ) & & ! ( gstate . lightEnable [ 2 ] & 1 ) & & ! ( gstate . lightEnable [ 3 ] & 1 ) )
2012-11-01 15:19:01 +00:00
{
2012-11-16 14:16:14 +00:00
disabled_ = true ;
2012-11-01 15:19:01 +00:00
}
2012-11-16 14:16:14 +00:00
materialEmissive . GetFromRGB ( gstate . materialemissive ) ;
materialEmissive . a = 0.0f ;
2012-11-01 15:19:01 +00:00
globalAmbient . GetFromRGB ( gstate . ambientcolor ) ;
globalAmbient . GetFromA ( gstate . ambientalpha ) ;
2012-11-16 14:16:14 +00:00
materialAmbient . GetFromRGB ( gstate . materialambient ) ;
materialAmbient . a = 1.0f ;
materialDiffuse . GetFromRGB ( gstate . materialdiffuse ) ;
materialDiffuse . a = 1.0f ;
materialSpecular . GetFromRGB ( gstate . materialspecular ) ;
materialSpecular . a = 1.0f ;
specCoef_ = getFloat24 ( gstate . materialspecularcoef ) ;
viewer_ = Vec3 ( - gstate . viewMatrix [ 9 ] , - gstate . viewMatrix [ 10 ] , - gstate . viewMatrix [ 11 ] ) ;
materialUpdate_ = gstate . materialupdate & 7 ;
}
void Lighter : : Light ( float colorOut0 [ 4 ] , float colorOut1 [ 4 ] , const float colorIn [ 4 ] , Vec3 pos , Vec3 normal , float dots [ 4 ] )
{
if ( disabled_ ) {
memcpy ( colorOut0 , colorIn , sizeof ( float ) * 4 ) ;
memset ( colorOut1 , 0 , sizeof ( float ) * 4 ) ;
return ;
}
2012-11-01 15:19:01 +00:00
Vec3 norm = normal . Normalized ( ) ;
Color4 in ( colorIn ) ;
2012-11-16 14:16:14 +00:00
const Color4 * ambient ;
if ( materialUpdate_ & 1 )
ambient = & in ;
2012-11-01 15:19:01 +00:00
else
2012-11-16 14:16:14 +00:00
ambient = & materialAmbient ;
2012-11-01 15:19:01 +00:00
2012-11-16 14:16:14 +00:00
const Color4 * diffuse ;
if ( materialUpdate_ & 2 )
diffuse = & in ;
2012-11-01 15:19:01 +00:00
else
2012-11-16 14:16:14 +00:00
diffuse = & materialDiffuse ;
2012-11-01 15:19:01 +00:00
2012-11-16 14:16:14 +00:00
const Color4 * specular ;
if ( materialUpdate_ & 4 )
specular = & in ;
2012-11-01 15:19:01 +00:00
else
2012-11-16 14:16:14 +00:00
specular = & materialSpecular ;
Color4 lightSum0 = globalAmbient * * ambient + materialEmissive ;
Color4 lightSum1 ( 0 , 0 , 0 , 0 ) ;
2012-11-01 15:19:01 +00:00
// Try lights.elf - there's something wrong with the lighting
for ( int l = 0 ; l < 4 ; l + + )
{
// can we skip this light?
2012-11-16 14:16:14 +00:00
if ( ( gstate . lightEnable [ l ] & 1 ) = = 0 & & ! doShadeMapping_ )
2012-11-11 18:00:44 +00:00
continue ;
2012-11-01 15:19:01 +00:00
GELightComputation comp = ( GELightComputation ) ( gstate . ltype [ l ] & 3 ) ;
GELightType type = ( GELightType ) ( ( gstate . ltype [ l ] > > 8 ) & 3 ) ;
Vec3 toLight ;
if ( type = = GE_LIGHTTYPE_DIRECTIONAL )
2012-11-09 16:51:45 +00:00
toLight = Vec3 ( gstate . lightpos [ l ] ) ; // lightdir is for spotlights
2012-11-01 15:19:01 +00:00
else
toLight = Vec3 ( gstate . lightpos [ l ] ) - pos ;
bool doSpecular = ( comp ! = GE_LIGHTCOMP_ONLYDIFFUSE ) ;
bool poweredDiffuse = comp = = GE_LIGHTCOMP_BOTHWITHPOWDIFFUSE ;
float lightScale = 1.0f ;
if ( type ! = GE_LIGHTTYPE_DIRECTIONAL )
{
2012-11-09 16:51:45 +00:00
float distance = toLight . Normalize ( ) ;
2012-11-01 15:19:01 +00:00
lightScale = 1.0f / ( gstate . lightatt [ l ] [ 0 ] + gstate . lightatt [ l ] [ 1 ] * distance + gstate . lightatt [ l ] [ 2 ] * distance * distance ) ;
2012-11-09 16:51:45 +00:00
if ( lightScale > 1.0f ) lightScale = 1.0f ;
2012-11-01 15:19:01 +00:00
}
float dot = toLight * norm ;
// Clamp dot to zero.
if ( dot < 0.0f ) dot = 0.0f ;
if ( poweredDiffuse )
2012-11-16 14:16:14 +00:00
dot = powf ( dot , specCoef_ ) ;
2012-11-01 15:19:01 +00:00
2012-11-16 14:16:14 +00:00
Color4 diff = ( gstate . lightColor [ 1 ] [ l ] * * diffuse ) * ( dot * lightScale ) ;
2012-11-01 15:19:01 +00:00
2012-11-09 16:51:45 +00:00
// Real PSP specular
Vec3 toViewer ( 0 , 0 , 1 ) ;
// Better specular
//Vec3 toViewer = (viewer - pos).Normalized();
2012-11-01 15:19:01 +00:00
if ( doSpecular )
{
Vec3 halfVec = toLight ;
2012-11-09 16:51:45 +00:00
halfVec + = toViewer ;
2012-11-01 15:19:01 +00:00
halfVec . Normalize ( ) ;
dot = halfVec * norm ;
if ( dot > = 0 )
{
2012-11-16 14:16:14 +00:00
lightSum1 + = ( gstate . lightColor [ 2 ] [ l ] * * specular * ( powf ( dot , specCoef_ ) * lightScale ) ) ;
2012-11-01 15:19:01 +00:00
}
}
dots [ l ] = dot ;
if ( gstate . lightEnable [ l ] & 1 )
{
2012-11-16 14:16:14 +00:00
lightSum0 + = gstate . lightColor [ 0 ] [ l ] * * ambient + diff ;
2012-11-01 15:19:01 +00:00
}
}
2012-11-16 14:16:14 +00:00
// 4?
for ( int i = 0 ; i < 4 ; i + + ) {
colorOut0 [ i ] = lightSum0 [ i ] ;
colorOut1 [ i ] = lightSum1 [ i ] ;
}
2012-11-01 15:19:01 +00:00
}
2012-11-16 14:16:14 +00:00
// This is the software transform pipeline, which is necessary for supporting RECT
// primitives correctly. Other primitives are possible to transform and light in hardware
// using vertex shader, which will be way, way faster, especially on mobile. This has
// not yet been implemented though.
2012-11-01 15:19:01 +00:00
void TransformAndDrawPrim ( void * verts , void * inds , int prim , int vertexCount , LinkedShader * program , float * customUV , int forceIndexType )
{
2012-11-16 15:19:37 +00:00
int indexLowerBound , indexUpperBound ;
2012-11-01 15:19:01 +00:00
// First, decode the verts and apply morphing
VertexDecoder dec ;
dec . SetVertexType ( gstate . vertType ) ;
2012-11-16 15:19:37 +00:00
dec . DecodeVerts ( decoded , verts , inds , prim , vertexCount , & indexLowerBound , & indexUpperBound ) ;
2012-11-01 15:19:01 +00:00
bool useTexCoord = false ;
// Check if anything needs updating
if ( gstate . textureChanged )
{
if ( gstate . textureMapEnable & & ! ( gstate . clearmode & 1 ) )
{
PSPSetTexture ( ) ;
useTexCoord = true ;
}
}
// Then, transform and draw in one big swoop (urgh!)
// need to move this to the shader.
// We're gonna have to keep software transforming RECTANGLES, unless we use a geom shader which we can't on OpenGL ES 2.0.
// Usually, though, these primitives don't use lighting etc so it's no biggie performance wise, but it would be nice to get rid of
// this code.
// Actually, if we find the camera-relative right and down vectors, it might even be possible to add the extra points in pre-transformed
// space and thus make decent use of hardware transform.
// Actually again, single quads could be drawn more efficiently using GL_TRIANGLE_STRIP, no need to duplicate verts as for
// GL_TRIANGLES. Still need to sw transform to compute the extra two corners though.
// Temporary storage for RECTANGLES emulation
float v2 [ 3 ] = { 0 } ;
float uv2 [ 2 ] = { 0 } ;
// TODO: Could use glDrawElements in some cases, see below.
// TODO: Split up into multiple draw calls for Android where you can't guarantee support for more than 0x10000 verts.
2012-11-05 13:09:49 +00:00
# if defined(ANDROID) || defined(BLACKBERRY)
2012-11-01 15:19:01 +00:00
if ( vertexCount > 0x10000 / 3 )
vertexCount = 0x10000 / 3 ;
# endif
2012-11-16 14:16:14 +00:00
Lighter lighter ;
2012-11-16 15:19:37 +00:00
for ( int index = indexLowerBound ; index < = indexUpperBound ; index + + )
2012-11-01 15:19:01 +00:00
{
2012-11-16 14:16:14 +00:00
float v [ 3 ] = { 0 , 0 , 0 } ;
float c0 [ 4 ] = { 1 , 1 , 1 , 1 } ;
float c1 [ 4 ] = { 0 , 0 , 0 , 0 } ;
float uv [ 2 ] = { 0 , 0 } ;
2012-11-01 15:19:01 +00:00
if ( gstate . vertType & GE_VTYPE_THROUGH_MASK )
{
// Do not touch the coordinates or the colors. No lighting.
for ( int j = 0 ; j < 3 ; j + + )
v [ j ] = decoded [ index ] . pos [ j ] ;
// TODO : check if has color
2012-11-16 14:16:14 +00:00
for ( int j = 0 ; j < 4 ; j + + ) {
c0 [ j ] = decoded [ index ] . color [ j ] / 255.0f ;
c1 [ j ] = 0.0f ;
}
2012-11-01 15:19:01 +00:00
// TODO : check if has uv
for ( int j = 0 ; j < 2 ; j + + )
uv [ j ] = decoded [ index ] . uv [ j ] ;
2012-11-09 16:51:45 +00:00
// Rescale UV?
2012-11-01 15:19:01 +00:00
}
else
{
2012-11-09 16:51:45 +00:00
// We do software T&L for now
2012-11-01 15:19:01 +00:00
float out [ 3 ] , norm [ 3 ] ;
if ( ( gstate . vertType & GE_VTYPE_WEIGHT_MASK ) = = GE_VTYPE_WEIGHT_NONE )
{
Vec3ByMatrix43 ( out , decoded [ index ] . pos , gstate . worldMatrix ) ;
Norm3ByMatrix43 ( norm , decoded [ index ] . normal , gstate . worldMatrix ) ;
}
else
{
2012-11-10 09:15:11 +00:00
// Skinning
2012-11-01 15:19:01 +00:00
Vec3 psum ( 0 , 0 , 0 ) ;
Vec3 nsum ( 0 , 0 , 0 ) ;
2012-11-11 18:07:07 +00:00
int nweights = ( ( gstate . vertType & GE_VTYPE_WEIGHTCOUNT_MASK ) > > GE_VTYPE_WEIGHTCOUNT_SHIFT ) + 1 ;
2012-11-11 18:03:48 +00:00
for ( int i = 0 ; i < nweights ; i + + )
2012-11-01 15:19:01 +00:00
{
2012-11-11 18:00:44 +00:00
if ( decoded [ index ] . weights [ i ] ! = 0.0f ) {
Vec3ByMatrix43 ( out , decoded [ index ] . pos , gstate . boneMatrix + i * 12 ) ;
Norm3ByMatrix43 ( norm , decoded [ index ] . normal , gstate . boneMatrix + i * 12 ) ;
Vec3 tpos ( out ) , tnorm ( norm ) ;
psum + = tpos * decoded [ index ] . weights [ i ] ;
nsum + = tnorm * decoded [ index ] . weights [ i ] ;
}
2012-11-01 15:19:01 +00:00
}
2012-11-11 16:54:13 +00:00
2012-11-01 15:19:01 +00:00
nsum . Normalize ( ) ;
2012-11-11 16:54:13 +00:00
Vec3ByMatrix43 ( out , psum . v , gstate . worldMatrix ) ;
Norm3ByMatrix43 ( norm , nsum . v , gstate . worldMatrix ) ;
2012-11-01 15:19:01 +00:00
}
// Perform lighting here if enabled. don't need to check through, it's checked above.
float dots [ 4 ] = { 0 , 0 , 0 , 0 } ;
if ( program - > a_color0 ! = - 1 )
{
2012-11-16 14:16:14 +00:00
float unlitColor [ 4 ] ;
for ( int j = 0 ; j < 4 ; j + + ) {
unlitColor [ j ] = decoded [ index ] . color [ j ] / 255.0f ;
}
float litColor0 [ 4 ] ;
float litColor1 [ 4 ] ;
lighter . Light ( litColor0 , litColor1 , unlitColor , out , norm , dots ) ;
2012-11-01 15:19:01 +00:00
if ( gstate . lightingEnable & 1 )
{
2012-11-16 14:16:14 +00:00
// TODO: don't ignore gstate.lmode - we should send two colors in that case
if ( gstate . lmode & 1 ) {
// Separate colors
for ( int j = 0 ; j < 4 ; j + + ) {
c0 [ j ] = litColor0 [ j ] ;
c1 [ j ] = litColor1 [ j ] ;
}
} else {
// Summed color into c0
for ( int j = 0 ; j < 4 ; j + + ) {
c0 [ j ] = litColor0 [ j ] + litColor1 [ j ] ;
c1 [ j ] = 0.0f ;
}
}
2012-11-01 15:19:01 +00:00
}
else
{
// no lighting? copy the color.
2012-11-16 14:16:14 +00:00
for ( int j = 0 ; j < 4 ; j + + ) {
c0 [ j ] = unlitColor [ j ] ;
c1 [ j ] = 0.0f ;
}
2012-11-01 15:19:01 +00:00
}
}
else
{
// no color in the fragment program???
2012-11-16 14:16:14 +00:00
for ( int j = 0 ; j < 4 ; j + + ) {
c0 [ j ] = decoded [ index ] . color [ j ] / 255.0f ;
c1 [ j ] = 0.0f ;
}
2012-11-01 15:19:01 +00:00
}
if ( customUV ) {
uv [ 0 ] = customUV [ index * 2 + 0 ] * gstate . uScale + gstate . uOff ;
uv [ 1 ] = customUV [ index * 2 + 1 ] * gstate . vScale + gstate . vOff ;
} else {
// Perform texture coordinate generation after the transform and lighting - one style of UV depends on lights.
switch ( gstate . texmapmode & 0x3 )
{
case 0 : // UV mapping
// Texture scale/offset is only performed in this mode.
uv [ 0 ] = decoded [ index ] . uv [ 0 ] * gstate . uScale + gstate . uOff ;
uv [ 1 ] = decoded [ index ] . uv [ 1 ] * gstate . vScale + gstate . vOff ;
break ;
case 1 :
{
// Projection mapping
Vec3 source ;
switch ( ( gstate . texmapmode > > 8 ) & 0x3 )
{
case 0 : // Use model space XYZ as source
source = decoded [ index ] . pos ;
break ;
case 1 : // Use unscaled UV as source
source = Vec3 ( decoded [ index ] . uv [ 0 ] , decoded [ index ] . uv [ 1 ] , 0.0f ) ;
break ;
case 2 : // Use normalized normal as source
source = Vec3 ( norm ) . Normalized ( ) ;
break ;
case 3 : // Use non-normalized normal as source!
source = Vec3 ( norm ) ;
break ;
}
float uvw [ 3 ] ;
Vec3ByMatrix43 ( uvw , & source . x , gstate . tgenMatrix ) ;
uv [ 0 ] = uvw [ 0 ] ;
uv [ 1 ] = uvw [ 1 ] ;
}
break ;
case 2 :
// Shade mapping
{
int lightsource1 = gstate . texshade & 0x3 ;
int lightsource2 = ( gstate . texshade > > 8 ) & 0x3 ;
uv [ 0 ] = dots [ lightsource1 ] ;
uv [ 1 ] = dots [ lightsource2 ] ;
}
break ;
case 3 :
// Illegal
break ;
}
}
2012-11-10 09:15:11 +00:00
2012-11-16 14:16:14 +00:00
// Transform the coord by the view matrix.
// We only really need to do it here for RECTANGLES drawing. However,
// there's no point in optimizing it out because all other primitives
// will be moved to hardware transform anyway.
2012-11-01 15:19:01 +00:00
Vec3ByMatrix43 ( v , out , gstate . viewMatrix ) ;
}
2012-11-16 15:19:37 +00:00
memcpy ( & transformed [ index ] . x , v , 3 * sizeof ( float ) ) ;
memcpy ( & transformed [ index ] . uv , uv , 2 * sizeof ( float ) ) ;
memcpy ( & transformed [ index ] . color0 , c0 , 4 * sizeof ( float ) ) ;
memcpy ( & transformed [ index ] . color1 , c1 , 4 * sizeof ( float ) ) ;
}
2012-11-01 15:19:01 +00:00
2012-11-16 15:19:37 +00:00
// Step 2: Expand using the index buffer, and expand rectangles.
const TransformedVertex * drawBuffer = transformed ;
int numTrans = 0 ;
int indexType = ( gstate . vertType & GE_VTYPE_IDX_MASK ) ;
if ( forceIndexType ! = - 1 ) {
indexType = forceIndexType ;
}
2012-11-16 15:43:16 +00:00
bool drawIndexed = false ;
GLuint glIndexType = 0 ;
if ( prim ! = GE_PRIM_RECTANGLES ) {
2012-11-16 15:19:37 +00:00
// We can simply draw the unexpanded buffer.
numTrans = vertexCount ;
2012-11-16 15:43:16 +00:00
switch ( indexType ) {
case GE_VTYPE_IDX_8BIT :
drawIndexed = true ;
glIndexType = GL_UNSIGNED_BYTE ;
break ;
case GE_VTYPE_IDX_16BIT :
drawIndexed = true ;
glIndexType = GL_UNSIGNED_SHORT ;
break ;
default :
drawIndexed = false ;
break ;
}
2012-11-16 15:19:37 +00:00
} else {
numTrans = 0 ;
drawBuffer = transformedExpanded ;
TransformedVertex * trans = & transformedExpanded [ 0 ] ;
TransformedVertex saved ;
for ( int i = 0 ; i < vertexCount ; i + + ) {
int index ;
if ( indexType = = GE_VTYPE_IDX_8BIT )
{
index = ( ( u8 * ) inds ) [ i ] ;
}
else if ( indexType = = GE_VTYPE_IDX_16BIT )
2012-11-01 15:19:01 +00:00
{
2012-11-16 15:19:37 +00:00
index = ( ( u16 * ) inds ) [ i ] ;
2012-11-01 15:19:01 +00:00
}
else
{
2012-11-16 15:19:37 +00:00
index = i ;
}
2012-11-01 15:19:01 +00:00
2012-11-16 15:19:37 +00:00
TransformedVertex & transVtx = transformed [ index ] ;
2012-11-16 15:43:16 +00:00
if ( ( i & 1 ) = = 0 )
2012-11-16 15:19:37 +00:00
{
2012-11-16 15:43:16 +00:00
// Save this vertex so we can generate when we get the next one. Color is taken from the last vertex.
saved = transVtx ;
2012-11-16 15:19:37 +00:00
}
2012-11-16 15:43:16 +00:00
else
2012-11-16 15:19:37 +00:00
{
2012-11-16 15:43:16 +00:00
// We have to turn the rectangle into two triangles, so 6 points. Sigh.
// top left
* trans = transVtx ;
trans + + ;
// bottom right
* trans = transVtx ;
trans - > x = saved . x ;
trans - > uv [ 0 ] = saved . uv [ 0 ] ;
trans - > y = saved . y ;
trans - > uv [ 1 ] = saved . uv [ 1 ] ;
trans + + ;
// top right
* trans = transVtx ;
trans - > x = saved . x ;
trans - > uv [ 0 ] = saved . uv [ 0 ] ;
trans + + ;
2012-11-16 16:19:28 +00:00
2012-11-16 15:43:16 +00:00
// bottom left
* trans = transVtx ;
trans - > y = saved . y ;
trans - > uv [ 1 ] = saved . uv [ 1 ] ;
trans + + ;
// bottom right
* trans = transVtx ;
trans - > x = saved . x ;
trans - > uv [ 0 ] = saved . uv [ 0 ] ;
trans - > y = saved . y ;
trans - > uv [ 1 ] = saved . uv [ 1 ] ;
trans + + ;
// top left
* trans = transVtx ;
trans + + ;
numTrans + = 6 ;
2012-11-01 15:19:01 +00:00
}
}
}
glEnableVertexAttribArray ( program - > a_position ) ;
if ( useTexCoord & & program - > a_texcoord ! = - 1 ) glEnableVertexAttribArray ( program - > a_texcoord ) ;
if ( program - > a_color0 ! = - 1 ) glEnableVertexAttribArray ( program - > a_color0 ) ;
2012-11-16 14:16:14 +00:00
if ( program - > a_color1 ! = - 1 ) glEnableVertexAttribArray ( program - > a_color1 ) ;
2012-11-16 15:19:37 +00:00
const int vertexSize = sizeof ( transformed [ 0 ] ) ;
glVertexAttribPointer ( program - > a_position , 3 , GL_FLOAT , GL_FALSE , vertexSize , drawBuffer ) ;
if ( useTexCoord & & program - > a_texcoord ! = - 1 ) glVertexAttribPointer ( program - > a_texcoord , 2 , GL_FLOAT , GL_FALSE , vertexSize , ( ( uint8_t * ) drawBuffer ) + 3 * 4 ) ;
if ( program - > a_color0 ! = - 1 ) glVertexAttribPointer ( program - > a_color0 , 4 , GL_FLOAT , GL_FALSE , vertexSize , ( ( uint8_t * ) drawBuffer ) + 5 * 4 ) ;
if ( program - > a_color1 ! = - 1 ) glVertexAttribPointer ( program - > a_color1 , 4 , GL_FLOAT , GL_FALSE , vertexSize , ( ( uint8_t * ) drawBuffer ) + 9 * 4 ) ;
2012-11-01 15:19:01 +00:00
// NOTICE_LOG(G3D,"DrawPrimitive: %i", numTrans);
2012-11-16 15:43:16 +00:00
if ( drawIndexed ) {
glDrawElements ( glprim [ prim ] , numTrans , glIndexType , ( GLvoid * ) inds ) ;
} else {
glDrawArrays ( glprim [ prim ] , 0 , numTrans ) ;
}
2012-11-01 15:19:01 +00:00
glDisableVertexAttribArray ( program - > a_position ) ;
if ( useTexCoord & & program - > a_texcoord ! = - 1 ) glDisableVertexAttribArray ( program - > a_texcoord ) ;
if ( program - > a_color0 ! = - 1 ) glDisableVertexAttribArray ( program - > a_color0 ) ;
2012-11-16 14:16:14 +00:00
if ( program - > a_color1 ! = - 1 ) glDisableVertexAttribArray ( program - > a_color1 ) ;
2012-11-01 15:19:01 +00:00
/*
if ( ( ( gstate . vertType ) & GE_VTYPE_IDX_MASK ) = = GE_VTYPE_IDX_8BIT )
{
glDrawElements ( glprim , vertexCount , GL_UNSIGNED_BYTE , inds ) ;
}
else if ( ( ( gstate . vertType ) & GE_VTYPE_IDX_MASK ) = = GE_VTYPE_IDX_16BIT )
{
glDrawElements ( glprim , vertexCount , GL_UNSIGNED_SHORT , inds ) ;
}
else
{ */
}