@ -504,6 +504,11 @@ public class GLRenderer implements Renderer {
// Initialize default state..
// Initialize default state..
gl . glPixelStorei ( GL . GL_UNPACK_ALIGNMENT , 1 ) ;
gl . glPixelStorei ( GL . GL_UNPACK_ALIGNMENT , 1 ) ;
if ( caps . contains ( Caps . SeamlessCubemap ) ) {
// Enable this globally. Should be OK.
gl . glEnable ( GLExt . GL_TEXTURE_CUBE_MAP_SEAMLESS ) ;
}
if ( caps . contains ( Caps . CoreProfile ) ) {
if ( caps . contains ( Caps . CoreProfile ) ) {
// Core Profile requires VAO to be bound.
// Core Profile requires VAO to be bound.
gl3 . glGenVertexArrays ( intBuf16 ) ;
gl3 . glGenVertexArrays ( intBuf16 ) ;
@ -609,13 +614,12 @@ public class GLRenderer implements Renderer {
if ( state . isDepthTest ( ) & & ! context . depthTestEnabled ) {
if ( state . isDepthTest ( ) & & ! context . depthTestEnabled ) {
gl . glEnable ( GL . GL_DEPTH_TEST ) ;
gl . glEnable ( GL . GL_DEPTH_TEST ) ;
gl . glDepthFunc ( convertTestFunction ( context . depthFunc ) ) ;
context . depthTestEnabled = true ;
context . depthTestEnabled = true ;
} else if ( ! state . isDepthTest ( ) & & context . depthTestEnabled ) {
} else if ( ! state . isDepthTest ( ) & & context . depthTestEnabled ) {
gl . glDisable ( GL . GL_DEPTH_TEST ) ;
gl . glDisable ( GL . GL_DEPTH_TEST ) ;
context . depthTestEnabled = false ;
context . depthTestEnabled = false ;
}
}
if ( state . getDepthFunc ( ) ! = context . depthFunc ) {
if ( state . isDepthTest ( ) & & state . getDepthFunc ( ) ! = context . depthFunc ) {
gl . glDepthFunc ( convertTestFunction ( state . getDepthFunc ( ) ) ) ;
gl . glDepthFunc ( convertTestFunction ( state . getDepthFunc ( ) ) ) ;
context . depthFunc = state . getDepthFunc ( ) ;
context . depthFunc = state . getDepthFunc ( ) ;
}
}
@ -1428,7 +1432,7 @@ public class GLRenderer implements Renderer {
// NOTE: For depth textures, sets nearest/no-mips mode
// NOTE: For depth textures, sets nearest/no-mips mode
// Required to fix "framebuffer unsupported"
// Required to fix "framebuffer unsupported"
// for old NVIDIA drivers!
// for old NVIDIA drivers!
setupTextureParams ( tex ) ;
setupTextureParams ( 0 , tex ) ;
}
}
glfbo . glFramebufferTexture2DEXT ( GLFbo . GL_FRAMEBUFFER_EXT ,
glfbo . glFramebufferTexture2DEXT ( GLFbo . GL_FRAMEBUFFER_EXT ,
@ -1812,7 +1816,7 @@ public class GLRenderer implements Renderer {
}
}
@SuppressWarnings ( "fallthrough" )
@SuppressWarnings ( "fallthrough" )
private void setupTextureParams ( Texture tex ) {
private void setupTextureParams ( int unit , Texture tex ) {
Image image = tex . getImage ( ) ;
Image image = tex . getImage ( ) ;
int target = convertTextureType ( tex . getType ( ) , image ! = null ? image . getMultiSamples ( ) : 1 , - 1 ) ;
int target = convertTextureType ( tex . getType ( ) , image ! = null ? image . getMultiSamples ( ) : 1 , - 1 ) ;
@ -1825,32 +1829,23 @@ public class GLRenderer implements Renderer {
// filter things
// filter things
if ( image . getLastTextureState ( ) . magFilter ! = tex . getMagFilter ( ) ) {
if ( image . getLastTextureState ( ) . magFilter ! = tex . getMagFilter ( ) ) {
int magFilter = convertMagFilter ( tex . getMagFilter ( ) ) ;
int magFilter = convertMagFilter ( tex . getMagFilter ( ) ) ;
bindTextureAndUnit ( target , image , unit ) ;
gl . glTexParameteri ( target , GL . GL_TEXTURE_MAG_FILTER , magFilter ) ;
gl . glTexParameteri ( target , GL . GL_TEXTURE_MAG_FILTER , magFilter ) ;
image . getLastTextureState ( ) . magFilter = tex . getMagFilter ( ) ;
image . getLastTextureState ( ) . magFilter = tex . getMagFilter ( ) ;
}
}
if ( image . getLastTextureState ( ) . minFilter ! = tex . getMinFilter ( ) ) {
if ( image . getLastTextureState ( ) . minFilter ! = tex . getMinFilter ( ) ) {
int minFilter = convertMinFilter ( tex . getMinFilter ( ) , haveMips ) ;
int minFilter = convertMinFilter ( tex . getMinFilter ( ) , haveMips ) ;
bindTextureAndUnit ( target , image , unit ) ;
gl . glTexParameteri ( target , GL . GL_TEXTURE_MIN_FILTER , minFilter ) ;
gl . glTexParameteri ( target , GL . GL_TEXTURE_MIN_FILTER , minFilter ) ;
image . getLastTextureState ( ) . minFilter = tex . getMinFilter ( ) ;
image . getLastTextureState ( ) . minFilter = tex . getMinFilter ( ) ;
}
}
if ( caps . contains ( Caps . SeamlessCubemap ) & & tex . getType ( ) = = Texture . Type . CubeMap ) {
if ( caps . contains ( Caps . TextureFilterAnisotropic )
if ( haveMips & & ! context . seamlessCubemap ) {
& & image . getLastTextureState ( ) . anisoFilter ! = tex . getAnisotropicFilter ( ) ) {
// We can enable seamless cubemap filtering.
bindTextureAndUnit ( target , image , unit ) ;
gl . glEnable ( GLExt . GL_TEXTURE_CUBE_MAP_SEAMLESS ) ;
context . seamlessCubemap = true ;
} else if ( ! haveMips & & context . seamlessCubemap ) {
// For skyboxes (no mipmaps), disable seamless cubemap filtering.
gl . glDisable ( GLExt . GL_TEXTURE_CUBE_MAP_SEAMLESS ) ;
context . seamlessCubemap = false ;
}
}
if ( tex . getAnisotropicFilter ( ) > 1 ) {
if ( caps . contains ( Caps . TextureFilterAnisotropic ) ) {
gl . glTexParameterf ( target ,
gl . glTexParameterf ( target ,
GLExt . GL_TEXTURE_MAX_ANISOTROPY_EXT ,
GLExt . GL_TEXTURE_MAX_ANISOTROPY_EXT ,
tex . getAnisotropicFilter ( ) ) ;
tex . getAnisotropicFilter ( ) ) ;
}
image . getLastTextureState ( ) . anisoFilter = tex . getAnisotropicFilter ( ) ;
}
}
// repeat modes
// repeat modes
@ -1858,6 +1853,7 @@ public class GLRenderer implements Renderer {
case ThreeDimensional :
case ThreeDimensional :
case CubeMap : // cubemaps use 3D coords
case CubeMap : // cubemaps use 3D coords
if ( gl2 ! = null & & image . getLastTextureState ( ) . rWrap ! = tex . getWrap ( WrapAxis . R ) ) {
if ( gl2 ! = null & & image . getLastTextureState ( ) . rWrap ! = tex . getWrap ( WrapAxis . R ) ) {
bindTextureAndUnit ( target , image , unit ) ;
gl2 . glTexParameteri ( target , GL2 . GL_TEXTURE_WRAP_R , convertWrapMode ( tex . getWrap ( WrapAxis . R ) ) ) ;
gl2 . glTexParameteri ( target , GL2 . GL_TEXTURE_WRAP_R , convertWrapMode ( tex . getWrap ( WrapAxis . R ) ) ) ;
image . getLastTextureState ( ) . rWrap = tex . getWrap ( WrapAxis . R ) ;
image . getLastTextureState ( ) . rWrap = tex . getWrap ( WrapAxis . R ) ;
}
}
@ -1865,10 +1861,12 @@ public class GLRenderer implements Renderer {
case TwoDimensional :
case TwoDimensional :
case TwoDimensionalArray :
case TwoDimensionalArray :
if ( image . getLastTextureState ( ) . tWrap ! = tex . getWrap ( WrapAxis . T ) ) {
if ( image . getLastTextureState ( ) . tWrap ! = tex . getWrap ( WrapAxis . T ) ) {
bindTextureAndUnit ( target , image , unit ) ;
gl . glTexParameteri ( target , GL . GL_TEXTURE_WRAP_T , convertWrapMode ( tex . getWrap ( WrapAxis . T ) ) ) ;
gl . glTexParameteri ( target , GL . GL_TEXTURE_WRAP_T , convertWrapMode ( tex . getWrap ( WrapAxis . T ) ) ) ;
image . getLastTextureState ( ) . tWrap = tex . getWrap ( WrapAxis . T ) ;
image . getLastTextureState ( ) . tWrap = tex . getWrap ( WrapAxis . T ) ;
}
}
if ( image . getLastTextureState ( ) . sWrap ! = tex . getWrap ( WrapAxis . S ) ) {
if ( image . getLastTextureState ( ) . sWrap ! = tex . getWrap ( WrapAxis . S ) ) {
bindTextureAndUnit ( target , image , unit ) ;
gl . glTexParameteri ( target , GL . GL_TEXTURE_WRAP_S , convertWrapMode ( tex . getWrap ( WrapAxis . S ) ) ) ;
gl . glTexParameteri ( target , GL . GL_TEXTURE_WRAP_S , convertWrapMode ( tex . getWrap ( WrapAxis . S ) ) ) ;
image . getLastTextureState ( ) . sWrap = tex . getWrap ( WrapAxis . S ) ;
image . getLastTextureState ( ) . sWrap = tex . getWrap ( WrapAxis . S ) ;
}
}
@ -1880,6 +1878,7 @@ public class GLRenderer implements Renderer {
if ( tex . isNeedCompareModeUpdate ( ) & & gl2 ! = null ) {
if ( tex . isNeedCompareModeUpdate ( ) & & gl2 ! = null ) {
// R to Texture compare mode
// R to Texture compare mode
if ( tex . getShadowCompareMode ( ) ! = Texture . ShadowCompareMode . Off ) {
if ( tex . getShadowCompareMode ( ) ! = Texture . ShadowCompareMode . Off ) {
bindTextureAndUnit ( target , image , unit ) ;
gl2 . glTexParameteri ( target , GL2 . GL_TEXTURE_COMPARE_MODE , GL2 . GL_COMPARE_R_TO_TEXTURE ) ;
gl2 . glTexParameteri ( target , GL2 . GL_TEXTURE_COMPARE_MODE , GL2 . GL_COMPARE_R_TO_TEXTURE ) ;
gl2 . glTexParameteri ( target , GL2 . GL_DEPTH_TEXTURE_MODE , GL2 . GL_INTENSITY ) ;
gl2 . glTexParameteri ( target , GL2 . GL_DEPTH_TEXTURE_MODE , GL2 . GL_INTENSITY ) ;
if ( tex . getShadowCompareMode ( ) = = Texture . ShadowCompareMode . GreaterOrEqual ) {
if ( tex . getShadowCompareMode ( ) = = Texture . ShadowCompareMode . GreaterOrEqual ) {
@ -1888,11 +1887,15 @@ public class GLRenderer implements Renderer {
gl2 . glTexParameteri ( target , GL2 . GL_TEXTURE_COMPARE_FUNC , GL . GL_LEQUAL ) ;
gl2 . glTexParameteri ( target , GL2 . GL_TEXTURE_COMPARE_FUNC , GL . GL_LEQUAL ) ;
}
}
} else {
} else {
bindTextureAndUnit ( target , image , unit ) ;
//restoring default value
//restoring default value
gl2 . glTexParameteri ( target , GL2 . GL_TEXTURE_COMPARE_MODE , GL . GL_NONE ) ;
gl2 . glTexParameteri ( target , GL2 . GL_TEXTURE_COMPARE_MODE , GL . GL_NONE ) ;
}
}
tex . compareModeUpdated ( ) ;
tex . compareModeUpdated ( ) ;
}
}
// If at this point we didn't bind the texture, bind it now
bindTextureOnly ( target , image , unit ) ;
}
}
/ * *
/ * *
@ -1950,6 +1953,50 @@ public class GLRenderer implements Renderer {
}
}
}
}
/ * *
* Ensures that the texture is bound to the given unit
* and that the unit is currently active ( for modification ) .
*
* @param target The texture target , one of GL_TEXTURE_ * * *
* @param img The image texture to bind
* @param unit At what unit to bind the texture .
* /
private void bindTextureAndUnit ( int target , Image img , int unit ) {
if ( context . boundTextureUnit ! = unit ) {
gl . glActiveTexture ( GL . GL_TEXTURE0 + unit ) ;
context . boundTextureUnit = unit ;
}
if ( context . boundTextures [ unit ] ! = img ) {
gl . glBindTexture ( target , img . getId ( ) ) ;
context . boundTextures [ unit ] = img ;
statistics . onTextureUse ( img , true ) ;
} else {
statistics . onTextureUse ( img , false ) ;
}
}
/ * *
* Ensures that the texture is bound to the given unit ,
* but does not care if the unit is active ( for rendering ) .
*
* @param target The texture target , one of GL_TEXTURE_ * * *
* @param img The image texture to bind
* @param unit At what unit to bind the texture .
* /
private void bindTextureOnly ( int target , Image img , int unit ) {
if ( context . boundTextures [ unit ] ! = img ) {
if ( context . boundTextureUnit ! = unit ) {
gl . glActiveTexture ( GL . GL_TEXTURE0 + unit ) ;
context . boundTextureUnit = unit ;
}
gl . glBindTexture ( target , img . getId ( ) ) ;
context . boundTextures [ unit ] = img ;
statistics . onTextureUse ( img , true ) ;
} else {
statistics . onTextureUse ( img , false ) ;
}
}
/ * *
/ * *
* Uploads the given image to the GL driver .
* Uploads the given image to the GL driver .
*
*
@ -1973,17 +2020,7 @@ public class GLRenderer implements Renderer {
// bind texture
// bind texture
int target = convertTextureType ( type , img . getMultiSamples ( ) , - 1 ) ;
int target = convertTextureType ( type , img . getMultiSamples ( ) , - 1 ) ;
if ( context . boundTextures [ unit ] ! = img ) {
bindTextureAndUnit ( target , img , unit ) ;
if ( context . boundTextureUnit ! = unit ) {
gl . glActiveTexture ( GL . GL_TEXTURE0 + unit ) ;
context . boundTextureUnit = unit ;
}
gl . glBindTexture ( target , texId ) ;
context . boundTextures [ unit ] = img ;
statistics . onTextureUse ( img , true ) ;
}
if ( ! img . hasMipmaps ( ) & & img . isGeneratedMipmapsRequired ( ) ) {
if ( ! img . hasMipmaps ( ) & & img . isGeneratedMipmapsRequired ( ) ) {
// Image does not have mipmaps, but they are required.
// Image does not have mipmaps, but they are required.
@ -2092,6 +2129,7 @@ public class GLRenderer implements Renderer {
img . clearUpdateNeeded ( ) ;
img . clearUpdateNeeded ( ) ;
}
}
@Override
public void setTexture ( int unit , Texture tex ) {
public void setTexture ( int unit , Texture tex ) {
Image image = tex . getImage ( ) ;
Image image = tex . getImage ( ) ;
if ( image . isUpdateNeeded ( ) | | ( image . isGeneratedMipmapsRequired ( ) & & ! image . isMipmapsGenerated ( ) ) ) {
if ( image . isUpdateNeeded ( ) | | ( image . isGeneratedMipmapsRequired ( ) & & ! image . isMipmapsGenerated ( ) ) ) {
@ -2118,24 +2156,7 @@ public class GLRenderer implements Renderer {
int texId = image . getId ( ) ;
int texId = image . getId ( ) ;
assert texId ! = - 1 ;
assert texId ! = - 1 ;
Image [ ] textures = context . boundTextures ;
setupTextureParams ( unit , tex ) ;
int type = convertTextureType ( tex . getType ( ) , image . getMultiSamples ( ) , - 1 ) ;
if ( textures [ unit ] ! = image ) {
if ( context . boundTextureUnit ! = unit ) {
gl . glActiveTexture ( GL . GL_TEXTURE0 + unit ) ;
context . boundTextureUnit = unit ;
}
gl . glBindTexture ( type , texId ) ;
textures [ unit ] = image ;
statistics . onTextureUse ( image , true ) ;
} else {
statistics . onTextureUse ( image , false ) ;
}
setupTextureParams ( tex ) ;
}
}
public void modifyTexture ( Texture tex , Image pixels , int x , int y ) {
public void modifyTexture ( Texture tex , Image pixels , int x , int y ) {
@ -2629,12 +2650,13 @@ public class GLRenderer implements Renderer {
}
}
}
}
clearVertexAttribs ( ) ;
if ( indices ! = null ) {
if ( indices ! = null ) {
drawTriangleList ( indices , mesh , count ) ;
drawTriangleList ( indices , mesh , count ) ;
} else {
} else {
drawTriangleArray ( mesh . getMode ( ) , count , mesh . getVertexCount ( ) ) ;
drawTriangleArray ( mesh . getMode ( ) , count , mesh . getVertexCount ( ) ) ;
}
}
clearVertexAttribs ( ) ;
}
}
public void renderMesh ( Mesh mesh , int lod , int count , VertexBuffer [ ] instanceData ) {
public void renderMesh ( Mesh mesh , int lod , int count , VertexBuffer [ ] instanceData ) {