@ -51,7 +51,9 @@ import com.jme3.texture.FrameBuffer;
import com.jme3.texture.FrameBuffer.RenderBuffer ;
import com.jme3.texture.FrameBuffer.RenderBuffer ;
import com.jme3.texture.Image ;
import com.jme3.texture.Image ;
import com.jme3.texture.Texture ;
import com.jme3.texture.Texture ;
import com.jme3.texture.Texture.ShadowCompareMode ;
import com.jme3.texture.Texture.WrapAxis ;
import com.jme3.texture.Texture.WrapAxis ;
import com.jme3.texture.image.LastTextureState ;
import com.jme3.util.BufferUtils ;
import com.jme3.util.BufferUtils ;
import com.jme3.util.ListMap ;
import com.jme3.util.ListMap ;
import com.jme3.util.MipMapGenerator ;
import com.jme3.util.MipMapGenerator ;
@ -68,7 +70,7 @@ import java.util.regex.Matcher;
import java.util.regex.Pattern ;
import java.util.regex.Pattern ;
import jme3tools.shader.ShaderDebug ;
import jme3tools.shader.ShaderDebug ;
public class GLRenderer implements Renderer {
public final class GLRenderer implements Renderer {
private static final Logger logger = Logger . getLogger ( GLRenderer . class . getName ( ) ) ;
private static final Logger logger = Logger . getLogger ( GLRenderer . class . getName ( ) ) ;
private static final boolean VALIDATE_SHADER = false ;
private static final boolean VALIDATE_SHADER = false ;
@ -374,15 +376,18 @@ public class GLRenderer implements Renderer {
if ( hasExtension ( "GL_EXT_texture_filter_anisotropic" ) ) {
if ( hasExtension ( "GL_EXT_texture_filter_anisotropic" ) ) {
caps . add ( Caps . TextureFilterAnisotropic ) ;
caps . add ( Caps . TextureFilterAnisotropic ) ;
limits . put ( Limits . TextureAnisotropy , getInteger ( GLExt . GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT ) ) ;
}
}
if ( hasExtension ( "GL_EXT_framebuffer_object" ) | | gl3 ! = null ) {
if ( hasExtension ( "GL_EXT_framebuffer_object" )
| | caps . contains ( Caps . OpenGL30 )
| | caps . contains ( Caps . OpenGLES20 ) ) {
caps . add ( Caps . FrameBuffer ) ;
caps . add ( Caps . FrameBuffer ) ;
limits . put ( Limits . RenderBufferSize , getInteger ( GLFbo . GL_MAX_RENDERBUFFER_SIZE_EXT ) ) ;
limits . put ( Limits . RenderBufferSize , getInteger ( GLFbo . GL_MAX_RENDERBUFFER_SIZE_EXT ) ) ;
limits . put ( Limits . FrameBufferAttachments , getInteger ( GLFbo . GL_MAX_COLOR_ATTACHMENTS_EXT ) ) ;
limits . put ( Limits . FrameBufferAttachments , getInteger ( GLFbo . GL_MAX_COLOR_ATTACHMENTS_EXT ) ) ;
if ( hasExtension ( "GL_EXT_framebuffer_blit" ) ) {
if ( hasExtension ( "GL_EXT_framebuffer_blit" ) | | caps . contains ( Caps . OpenGL30 ) ) {
caps . add ( Caps . FrameBufferBlit ) ;
caps . add ( Caps . FrameBufferBlit ) ;
}
}
@ -401,7 +406,7 @@ public class GLRenderer implements Renderer {
}
}
}
}
if ( hasExtension ( "GL_ARB_draw_buffers" ) ) {
if ( hasExtension ( "GL_ARB_draw_buffers" ) | | caps . contains ( Caps . OpenGL30 ) ) {
limits . put ( Limits . FrameBufferMrtAttachments , getInteger ( GLExt . GL_MAX_DRAW_BUFFERS_ARB ) ) ;
limits . put ( Limits . FrameBufferMrtAttachments , getInteger ( GLExt . GL_MAX_DRAW_BUFFERS_ARB ) ) ;
if ( limits . get ( Limits . FrameBufferMrtAttachments ) > 1 ) {
if ( limits . get ( Limits . FrameBufferMrtAttachments ) > 1 ) {
caps . add ( Caps . FrameBufferMRT ) ;
caps . add ( Caps . FrameBufferMRT ) ;
@ -502,6 +507,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 ) ;
@ -607,13 +617,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 ( ) ;
}
}
@ -1064,6 +1073,9 @@ public class GLRenderer implements Renderer {
stringBuf . append ( "\n" ) ;
stringBuf . append ( "\n" ) ;
} else {
} else {
if ( gles2 ) {
if ( gles2 ) {
// request GLSL ES (1.00) when compiling under GLES2.
stringBuf . append ( "#version 100\n" ) ;
if ( source . getType ( ) = = ShaderType . Fragment ) {
if ( source . getType ( ) = = ShaderType . Fragment ) {
// GLES2 requires precision qualifier.
// GLES2 requires precision qualifier.
stringBuf . append ( "precision mediump float;\n" ) ;
stringBuf . append ( "precision mediump float;\n" ) ;
@ -1080,6 +1092,7 @@ public class GLRenderer implements Renderer {
if ( linearizeSrgbImages ) {
if ( linearizeSrgbImages ) {
stringBuf . append ( "#define SRGB 1\n" ) ;
stringBuf . append ( "#define SRGB 1\n" ) ;
}
}
stringBuf . append ( "#define " ) . append ( source . getType ( ) . name ( ) . toUpperCase ( ) ) . append ( "_SHADER 1\n" ) ;
stringBuf . append ( source . getDefines ( ) ) ;
stringBuf . append ( source . getDefines ( ) ) ;
stringBuf . append ( source . getSource ( ) ) ;
stringBuf . append ( source . getSource ( ) ) ;
@ -1422,7 +1435,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 ,
@ -1450,24 +1463,43 @@ public class GLRenderer implements Renderer {
}
}
}
}
private void bindFrameBuffer ( FrameBuffer fb ) {
if ( fb = = null ) {
if ( context . boundFBO ! = 0 ) {
glfbo . glBindFramebufferEXT ( GLFbo . GL_FRAMEBUFFER_EXT , 0 ) ;
statistics . onFrameBufferUse ( null , true ) ;
context . boundFBO = 0 ;
context . boundFB = null ;
}
} else {
assert fb . getId ( ) ! = - 1 & & fb . getId ( ) ! = 0 ;
if ( context . boundFBO ! = fb . getId ( ) ) {
glfbo . glBindFramebufferEXT ( GLFbo . GL_FRAMEBUFFER_EXT , fb . getId ( ) ) ;
context . boundFBO = fb . getId ( ) ;
context . boundFB = fb ;
statistics . onFrameBufferUse ( fb , true ) ;
} else {
statistics . onFrameBufferUse ( fb , false ) ;
}
}
}
public void updateFrameBuffer ( FrameBuffer fb ) {
public void updateFrameBuffer ( FrameBuffer fb ) {
if ( fb . getNumColorBuffers ( ) = = 0 & & fb . getDepthBuffer ( ) = = null ) {
throw new IllegalArgumentException ( "The framebuffer: " + fb
+ "\nDoesn't have any color/depth buffers" ) ;
}
int id = fb . getId ( ) ;
int id = fb . getId ( ) ;
if ( id = = - 1 ) {
if ( id = = - 1 ) {
// create FBO
glfbo . glGenFramebuffersEXT ( intBuf1 ) ;
glfbo . glGenFramebuffersEXT ( intBuf1 ) ;
id = intBuf1 . get ( 0 ) ;
id = intBuf1 . get ( 0 ) ;
fb . setId ( id ) ;
fb . setId ( id ) ;
objManager . registerObject ( fb ) ;
objManager . registerObject ( fb ) ;
statistics . onNewFrameBuffer ( ) ;
statistics . onNewFrameBuffer ( ) ;
}
}
if ( context . boundFBO ! = id ) {
bindFrameBuffer ( fb ) ;
glfbo . glBindFramebufferEXT ( GLFbo . GL_FRAMEBUFFER_EXT , id ) ;
// binding an FBO automatically sets draw buf to GL_COLOR_ATTACHMENT0
context . boundDrawBuf = 0 ;
context . boundFBO = id ;
}
FrameBuffer . RenderBuffer depthBuf = fb . getDepthBuffer ( ) ;
FrameBuffer . RenderBuffer depthBuf = fb . getDepthBuffer ( ) ;
if ( depthBuf ! = null ) {
if ( depthBuf ! = null ) {
@ -1479,6 +1511,7 @@ public class GLRenderer implements Renderer {
updateFrameBufferAttachment ( fb , colorBuf ) ;
updateFrameBufferAttachment ( fb , colorBuf ) ;
}
}
setReadDrawBuffers ( fb ) ;
checkFrameBufferError ( ) ;
checkFrameBufferError ( ) ;
fb . clearUpdateNeeded ( ) ;
fb . clearUpdateNeeded ( ) ;
@ -1506,93 +1539,45 @@ public class GLRenderer implements Renderer {
}
}
public void setMainFrameBufferOverride ( FrameBuffer fb ) {
public void setMainFrameBufferOverride ( FrameBuffer fb ) {
mainFbOverride = fb ;
mainFbOverride = null ;
if ( context . boundFBO = = 0 ) {
// Main FB is now set to fb, make sure its bound
setFrameBuffer ( fb ) ;
}
}
mainFbOverride = fb ;
public void setFrameBuffer ( FrameBuffer fb ) {
if ( fb = = null & & mainFbOverride ! = null ) {
fb = mainFbOverride ;
}
}
if ( context . boundFB = = fb ) {
public void setReadDrawBuffers ( FrameBuffer fb ) {
if ( fb = = null | | ! fb . isUpdateNeeded ( ) ) {
if ( gl2 = = null ) {
return ;
return ;
}
}
}
if ( ! caps . contains ( Caps . FrameBuffer ) ) {
final int NONE = - 2 ;
throw new RendererException ( "Framebuffer objects are not supported"
final int INITIAL = - 1 ;
+ " by the video hardware" ) ;
final int MRT_OFF = 100 ;
}
// generate mipmaps for last FB if needed
if ( context . boundFB ! = null ) {
for ( int i = 0 ; i < context . boundFB . getNumColorBuffers ( ) ; i + + ) {
RenderBuffer rb = context . boundFB . getColorBuffer ( i ) ;
Texture tex = rb . getTexture ( ) ;
if ( tex ! = null
& & tex . getMinFilter ( ) . usesMipMapLevels ( ) ) {
setTexture ( 0 , rb . getTexture ( ) ) ;
int textureType = convertTextureType ( tex . getType ( ) , tex . getImage ( ) . getMultiSamples ( ) , rb . getFace ( ) ) ;
glfbo . glGenerateMipmapEXT ( textureType ) ;
}
}
}
if ( fb = = null ) {
if ( fb = = null ) {
// unbind any fbos
// Set Read/Draw buffers to initial value.
if ( context . boundFBO ! = 0 ) {
if ( context . boundDrawBuf ! = INITIAL ) {
glfbo . glBindFramebufferEXT ( GLFbo . GL_FRAMEBUFFER_EXT , 0 ) ;
statistics . onFrameBufferUse ( null , true ) ;
context . boundFBO = 0 ;
}
// select back buffer
if ( gl2 ! = null ) {
if ( context . boundDrawBuf ! = - 1 ) {
gl2 . glDrawBuffer ( context . initialDrawBuf ) ;
gl2 . glDrawBuffer ( context . initialDrawBuf ) ;
context . boundDrawBuf = - 1 ;
context . boundDrawBuf = INITIAL ;
}
}
if ( context . boundReadBuf ! = - 1 ) {
if ( context . boundReadBuf ! = INITIAL ) {
gl2 . glReadBuffer ( context . initialReadBuf ) ;
gl2 . glReadBuffer ( context . initialReadBuf ) ;
context . boundReadBuf = - 1 ;
context . boundReadBuf = INITIAL ;
}
}
context . boundFB = null ;
} else {
if ( fb . getNumColorBuffers ( ) = = 0 & & fb . getDepthBuffer ( ) = = null ) {
throw new IllegalArgumentException ( "The framebuffer: " + fb
+ "\nDoesn't have any color/depth buffers" ) ;
}
if ( fb . isUpdateNeeded ( ) ) {
updateFrameBuffer ( fb ) ;
}
}
// update viewport to reflect framebuffer's resolution
setViewPort ( 0 , 0 , fb . getWidth ( ) , fb . getHeight ( ) ) ;
if ( context . boundFBO ! = fb . getId ( ) ) {
glfbo . glBindFramebufferEXT ( GLFbo . GL_FRAMEBUFFER_EXT , fb . getId ( ) ) ;
statistics . onFrameBufferUse ( fb , true ) ;
context . boundFBO = fb . getId ( ) ;
} else {
} else {
statistics . onFrameBufferUse ( fb , false ) ;
}
if ( fb . getNumColorBuffers ( ) = = 0 ) {
if ( fb . getNumColorBuffers ( ) = = 0 ) {
// make sure to select NONE as draw buf
// make sure to select NONE as draw buf
// no color buffer attached. select NONE
// no color buffer attached.
if ( gl2 ! = null ) {
if ( gl2 ! = null ) {
if ( context . boundDrawBuf ! = - 2 ) {
if ( context . boundDrawBuf ! = NONE ) {
gl2 . glDrawBuffer ( GL . GL_NONE ) ;
gl2 . glDrawBuffer ( GL . GL_NONE ) ;
context . boundDrawBuf = - 2 ;
context . boundDrawBuf = NONE ;
}
}
if ( context . boundReadBuf ! = - 2 ) {
if ( context . boundReadBuf ! = NONE ) {
gl2 . glReadBuffer ( GL . GL_NONE ) ;
gl2 . glReadBuffer ( GL . GL_NONE ) ;
context . boundReadBuf = - 2 ;
context . boundReadBuf = NONE ;
}
}
}
}
} else {
} else {
@ -1612,7 +1597,7 @@ public class GLRenderer implements Renderer {
+ " by the video hardware!" ) ;
+ " by the video hardware!" ) ;
}
}
if ( context . boundDrawBuf ! = 100 + fb . getNumColorBuffers ( ) ) {
if ( context . boundDrawBuf ! = MRT_OFF + fb . getNumColorBuffers ( ) ) {
intBuf16 . clear ( ) ;
intBuf16 . clear ( ) ;
for ( int i = 0 ; i < fb . getNumColorBuffers ( ) ; i + + ) {
for ( int i = 0 ; i < fb . getNumColorBuffers ( ) ; i + + ) {
intBuf16 . put ( GLFbo . GL_COLOR_ATTACHMENT0_EXT + i ) ;
intBuf16 . put ( GLFbo . GL_COLOR_ATTACHMENT0_EXT + i ) ;
@ -1620,7 +1605,7 @@ public class GLRenderer implements Renderer {
intBuf16 . flip ( ) ;
intBuf16 . flip ( ) ;
glext . glDrawBuffers ( intBuf16 ) ;
glext . glDrawBuffers ( intBuf16 ) ;
context . boundDrawBuf = 100 + fb . getNumColorBuffers ( ) ;
context . boundDrawBuf = MRT_OFF + fb . getNumColorBuffers ( ) ;
}
}
} else {
} else {
RenderBuffer rb = fb . getColorBuffer ( fb . getTargetIndex ( ) ) ;
RenderBuffer rb = fb . getColorBuffer ( fb . getTargetIndex ( ) ) ;
@ -1633,8 +1618,56 @@ public class GLRenderer implements Renderer {
}
}
}
}
}
}
}
}
public void setFrameBuffer ( FrameBuffer fb ) {
if ( fb = = null & & mainFbOverride ! = null ) {
fb = mainFbOverride ;
}
if ( context . boundFB = = fb ) {
if ( fb = = null | | ! fb . isUpdateNeeded ( ) ) {
return ;
}
}
if ( ! caps . contains ( Caps . FrameBuffer ) ) {
throw new RendererException ( "Framebuffer objects are not supported"
+ " by the video hardware" ) ;
}
assert fb . getId ( ) > = 0 ;
// generate mipmaps for last FB if needed
if ( context . boundFB ! = null ) {
for ( int i = 0 ; i < context . boundFB . getNumColorBuffers ( ) ; i + + ) {
RenderBuffer rb = context . boundFB . getColorBuffer ( i ) ;
Texture tex = rb . getTexture ( ) ;
if ( tex ! = null
& & tex . getMinFilter ( ) . usesMipMapLevels ( ) ) {
setTexture ( 0 , rb . getTexture ( ) ) ;
int textureType = convertTextureType ( tex . getType ( ) , tex . getImage ( ) . getMultiSamples ( ) , rb . getFace ( ) ) ;
glfbo . glGenerateMipmapEXT ( textureType ) ;
}
}
}
if ( fb = = null ) {
bindFrameBuffer ( null ) ;
setReadDrawBuffers ( null ) ;
} else {
if ( fb . isUpdateNeeded ( ) ) {
updateFrameBuffer ( fb ) ;
} else {
bindFrameBuffer ( fb ) ;
setReadDrawBuffers ( fb ) ;
}
// update viewport to reflect framebuffer's resolution
setViewPort ( 0 , 0 , fb . getWidth ( ) , fb . getHeight ( ) ) ;
assert fb . getId ( ) > 0 ;
assert context . boundFBO = = fb . getId ( ) ;
assert context . boundFBO = = fb . getId ( ) ;
context . boundFB = fb ;
context . boundFB = fb ;
@ -1806,87 +1839,80 @@ 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 ) ;
boolean haveMips = true ;
boolean haveMips = true ;
if ( image ! = null ) {
if ( image ! = null ) {
haveMips = image . isGeneratedMipmapsRequired ( ) | | image . hasMipmaps ( ) ;
haveMips = image . isGeneratedMipmapsRequired ( ) | | image . hasMipmaps ( ) ;
}
}
// filter things
LastTextureState curState = image . getLastTextureState ( ) ;
if ( image . getLastTextureState ( ) . magFilter ! = tex . getMagFilter ( ) ) {
int magFilter = convertMagFilter ( tex . getMagFilter ( ) ) ;
if ( curState . magFilter ! = tex . getMagFilter ( ) ) {
gl . glTexParameteri ( target , GL . GL_TEXTURE_MAG_FILTER , magFilter ) ;
bindTextureAndUnit ( target , image , unit ) ;
image . getLastTextureState ( ) . magFilter = tex . getMagFilter ( ) ;
gl . glTexParameteri ( target , GL . GL_TEXTURE_MAG_FILTER , convertMagFilter ( tex . getMagFilter ( ) ) ) ;
}
curState . magFilter = tex . getMagFilter ( ) ;
if ( image . getLastTextureState ( ) . minFilter ! = tex . getMinFilter ( ) ) {
int minFilter = convertMinFilter ( tex . getMinFilter ( ) , haveMips ) ;
gl . glTexParameteri ( target , GL . GL_TEXTURE_MIN_FILTER , minFilter ) ;
image . getLastTextureState ( ) . minFilter = tex . getMinFilter ( ) ;
}
if ( caps . contains ( Caps . SeamlessCubemap ) & & tex . getType ( ) = = Texture . Type . CubeMap ) {
if ( haveMips & & ! context . seamlessCubemap ) {
// We can enable seamless cubemap filtering.
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 ( curState . minFilter ! = tex . getMinFilter ( ) ) {
bindTextureAndUnit ( target , image , unit ) ;
gl . glTexParameteri ( target , GL . GL_TEXTURE_MIN_FILTER , convertMinFilter ( tex . getMinFilter ( ) , haveMips ) ) ;
curState . minFilter = tex . getMinFilter ( ) ;
}
}
if ( caps . contains ( Caps . TextureFilterAnisotropic )
if ( tex . getAnisotropicFilter ( ) > 1 ) {
& & curState . anisoFilter ! = tex . getAnisotropicFilter ( ) ) {
if ( caps . contains ( Caps . TextureFilterAnisotropic ) ) {
bindTextureAndUnit ( target , image , unit ) ;
gl . glTexParameterf ( target ,
gl . glTexParameterf ( target ,
GLExt . GL_TEXTURE_MAX_ANISOTROPY_EXT ,
GLExt . GL_TEXTURE_MAX_ANISOTROPY_EXT ,
tex . getAnisotropicFilter ( ) ) ;
tex . getAnisotropicFilter ( ) ) ;
}
curState . anisoFilter = tex . getAnisotropicFilter ( ) ;
}
}
// repeat modes
switch ( tex . getType ( ) ) {
switch ( tex . getType ( ) ) {
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 & & curState . 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 . getLastText ure State( ) . rWrap = tex . getWrap ( WrapAxis . R ) ;
c urState. rWrap = tex . getWrap ( WrapAxis . R ) ;
}
}
//There is no break statement on purpose here
//There is no break statement on purpose here
case TwoDimensional :
case TwoDimensional :
case TwoDimensionalArray :
case TwoDimensionalArray :
if ( image . getLastTextureState ( ) . tWrap ! = tex . getWrap ( WrapAxis . T ) ) {
if ( curState . 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 ( curState . 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 . getLastText ure State( ) . sWrap = tex . getWrap ( WrapAxis . S ) ;
c urState. sWrap = tex . getWrap ( WrapAxis . S ) ;
}
}
break ;
break ;
default :
default :
throw new UnsupportedOperationException ( "Unknown texture type: " + tex . getType ( ) ) ;
throw new UnsupportedOperationException ( "Unknown texture type: " + tex . getType ( ) ) ;
}
}
if ( tex . isNeedCompareModeUpdate ( ) & & gl2 ! = null ) {
ShadowCompareMode texCompareMode = tex . getShadowCompareMode ( ) ;
// R to Texture compare mode
if ( gl2 ! = null & & curState . shadowCompareMode ! = texCompareMode ) {
if ( tex . getShadowCompareMode ( ) ! = Texture . ShadowCompareMode . Off ) {
bindTextureAndUnit ( target , image , unit ) ;
gl2 . glTexParameteri ( target , GL2 . GL_TEXTURE_COMPARE_MODE , GL2 . GL_COMPARE_R_TO_TEXTURE ) ;
if ( texCompareMode ! = ShadowCompareMode . Off ) {
gl2 . glTexParameteri ( target , GL2 . GL_DEPTH_ TEXTURE_MODE , GL2 . GL_INTENSITY ) ;
gl2 . glTexParameteri ( target , GL2 . GL_TEXTURE_COMPA RE_MODE , GL2 . GL_COMPARE_REF_TO_TEXTURE ) ;
if ( tex . getShadow CompareMode( ) = = Texture . ShadowCompareMode . GreaterOrEqual ) {
if ( texCompareMode = = ShadowCompareMode . GreaterOrEqual ) {
gl2 . glTexParameteri ( target , GL2 . GL_TEXTURE_COMPARE_FUNC , GL . GL_GEQUAL ) ;
gl2 . glTexParameteri ( target , GL2 . GL_TEXTURE_COMPARE_FUNC , GL . GL_GEQUAL ) ;
} else {
} else {
gl2 . glTexParameteri ( target , GL2 . GL_TEXTURE_COMPARE_FUNC , GL . GL_LEQUAL ) ;
gl2 . glTexParameteri ( target , GL2 . GL_TEXTURE_COMPARE_FUNC , GL . GL_LEQUAL ) ;
}
}
} else {
} else {
//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 ( ) ;
curState . shadowCompareMode = texCompareMode ;
}
}
// If at this point we didn't bind the texture, bind it now
bindTextureOnly ( target , image , unit ) ;
}
}
/ * *
/ * *
@ -1944,6 +1970,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 .
*
*
@ -1967,17 +2037,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.
@ -2086,6 +2146,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 ( ) ) ) {
@ -2112,24 +2173,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 ) {
@ -2623,12 +2667,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 ) {