# PySoy's materials.Textured class # # Copyright (C) 2006,2007,2008,2009 PySoy Group # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as published # by the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # 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 Affero General Public License for more details. # # You should have received a copy of the GNU Affero General Public License # along with this program; if not, see http://www.gnu.org/licenses # # $Id: Textured.pym 1393 2008-12-31 23:51:25Z ArcRiley $ cdef class Textured(Material) : '''soy.materials.Textured Textured materials support one or more basic textures in addition to the standard Material colors (ambient, diffuse, specular, emission) which are multiplied by the texture color to provide light-based shading. Currently .bumpmap .colormap and .glowmap are supported. ''' ############################################################################ # # Python functions # def __cinit__(self, soy.colors.Color ambient=None, soy.colors.Color diffuse=None, soy.colors.Color specular=None, soy.colors.Color emission=None, float shininess=0.5, soy.textures.Texture bumpmap=None, soy.textures.Texture colormap=None, soy.textures.Texture glowmap=None, *args, **keywords) : ###################################### # # store the texture arguments # self._bumpmap = bumpmap self._colormap = colormap self._glowmap = glowmap # ###################################### ############################################################################ # # Properties # property colormap : '''soy.materials.Textured.colormap When a texture is assigned to this property a colormap texture is rendered. In OpenGL terms, this texture is set GL_MODULATE to the lit material color which provides it's shading. Textures with an alpha component will be translucent to the material's lit color, so to achieve actual translucency this material's colors (ambient/diffuse) must also be translucent. Default is None (disabled). ''' def __get__(self) : return self._colormap def __set__(self, soy.textures.Texture _value) : self._colormap = _value def __del__(self) : self._colormap = None property glowmap : '''soy.materials.Textured.glowmap When a texture is assigned to this property a glowmap texture is rendered. In OpenGL terms, this texture is set GL_ADD. Default is None (disabled). ''' def __get__(self) : return self._glowmap def __set__(self, soy.textures.Texture _value) : self._glowmap = _value def __del__(self) : self._glowmap = None property bumpmap : '''soy.materials.Textured.bumpmap When a texture is assigned to this property a bumpmap texture is rendered. This allows artists to add fine-grained detail to 3d objects or the give otherwise smooth/flat surfaces a pattered appearance that changes with the angle of light (shadows/highlights). In OpenGL terms, this texture is a dot3 normal map in tangent-space which is mapped to object space by combining it with a normalisation cubemap. Default is None (disabled). ''' def __get__(self) : return self._bumpmap def __set__(self, soy.textures.Texture _value) : if _value._chans != 3 : raise ValueError('bumpmaps must be RGB') self._bumpmap = _value def __del__(self) : self._bumpmap = None ############################################################################ # # General C functions # cdef int _isTransparent(self) nogil : # # textures are only translucent to the colors, so if either lack # translucency this check will return False # if self._colormap is not None and self._colormap._chans %2 == 1 : return 0 if self._ambient._rgba[3] != 1.0 : return 1 if self._diffuse._rgba[3] != 1.0 : return 1 return 0 cdef int _needsTSLVs(self) nogil : ###################################### # # this material usually needs TSLV # return 1 # ###################################### ############################################################################ # # WindowLoop functions # cdef int _render(self, int _pass, float* _texcoords, float* _tslvs) nogil : cdef int _i, _bump, _unit _unit = 0 _bump = 0; ###################################### # # if there's no bumpmap, render it like a textured material # if self._bumpmap is None : _pass += 1 else : _bump = 1 # ###################################### # # this will only be true if _pass==0 and bumpmap is not None # if _pass == 0 : #################################### # # Texture1 - the normalisation cubemap # gl.glActiveTexture(gl.GL_TEXTURE1) gl.glClientActiveTexture(gl.GL_TEXTURE1) gl.glEnableClientState(gl.GL_TEXTURE_COORD_ARRAY) gl.glTexCoordPointer(3, gl.GL_FLOAT, 0, _tslvs) _normalisation_cube_map._enable() gl.glTexEnvi(gl.GL_TEXTURE_ENV, gl.GL_TEXTURE_ENV_MODE, gl.GL_COMBINE) gl.glTexEnvi(gl.GL_TEXTURE_ENV, gl.GL_SOURCE0_RGB, gl.GL_TEXTURE) gl.glTexEnvi(gl.GL_TEXTURE_ENV, gl.GL_SOURCE1_RGB, gl.GL_PREVIOUS) gl.glTexEnvi(gl.GL_TEXTURE_ENV, gl.GL_COMBINE_RGB, gl.GL_DOT3_RGB) gl.glTexParameteri(gl.GL_TEXTURE_CUBE_MAP, gl.GL_TEXTURE_MAG_FILTER, gl.GL_LINEAR) gl.glTexParameteri(gl.GL_TEXTURE_CUBE_MAP, gl.GL_TEXTURE_MIN_FILTER, gl.GL_LINEAR) gl.glTexParameteri(gl.GL_TEXTURE_CUBE_MAP, gl.GL_TEXTURE_WRAP_S, gl.GL_CLAMP_TO_EDGE) gl.glTexParameteri(gl.GL_TEXTURE_CUBE_MAP, gl.GL_TEXTURE_WRAP_T, gl.GL_CLAMP_TO_EDGE) gl.glTexParameteri(gl.GL_TEXTURE_CUBE_MAP, gl.GL_TEXTURE_WRAP_R, gl.GL_CLAMP_TO_EDGE) # #################################### # # Texture0 - the dot3 normal map (bumpmap) # gl.glActiveTexture(gl.GL_TEXTURE0) gl.glClientActiveTexture(gl.GL_TEXTURE0) gl.glEnableClientState(gl.GL_TEXTURE_COORD_ARRAY) gl.glTexCoordPointer(3, gl.GL_FLOAT, 48, _texcoords) self._bumpmap._enable() gl.glTexEnvi(gl.GL_TEXTURE_ENV, gl.GL_TEXTURE_ENV_MODE, gl.GL_COMBINE) gl.glTexEnvi(gl.GL_TEXTURE_ENV, gl.GL_SOURCE0_RGB, gl.GL_TEXTURE) gl.glTexEnvi(gl.GL_TEXTURE_ENV, gl.GL_COMBINE_RGB, gl.GL_REPLACE) # #################################### # # either return now and render 2-pass or play a trick # no tricks yet # return 1 # ###################################### # # Render non-bumpmap passes # if _pass == 1 : if _bump : ################################## # # start by cleaning up from last pass # gl.glActiveTexture(gl.GL_TEXTURE1) gl.glClientActiveTexture(gl.GL_TEXTURE1) _normalisation_cube_map._disable() gl.glDisableClientState(gl.GL_TEXTURE_COORD_ARRAY) gl.glActiveTexture(gl.GL_TEXTURE0) gl.glClientActiveTexture(gl.GL_TEXTURE0) self._bumpmap._disable() # ################################## # # also setup blending for this pass # gl.glEnable(gl.GL_BLEND) gl.glBlendFunc(gl.GL_DST_COLOR, gl.GL_ZERO) gl.glEnable(gl.GL_POLYGON_OFFSET_FILL) gl.glPolygonOffset(0,-2) # #################################### # # number of shades, currently just 0 or 1 # if self._shades == 0 : gl.glShadeModel(gl.GL_SMOOTH) else : gl.glShadeModel(gl.GL_FLAT) # #################################### # # lit material colors and settings # gl.glMaterialfv(gl.GL_FRONT, gl.GL_AMBIENT, self._ambient._rgba) gl.glMaterialfv(gl.GL_FRONT, gl.GL_DIFFUSE, self._diffuse._rgba) gl.glMaterialfv(gl.GL_FRONT, gl.GL_SPECULAR, self._specular._rgba) gl.glMaterialfv(gl.GL_FRONT, gl.GL_EMISSION, self._emission._rgba) gl.glMaterialf (gl.GL_FRONT, gl.GL_SHININESS, self._shininess) # #################################### # # render the colormap # if self._colormap is not None : gl.glActiveTexture(_texunits[_unit]) gl.glClientActiveTexture(_texunits[_unit]) gl.glEnableClientState(gl.GL_TEXTURE_COORD_ARRAY) gl.glTexCoordPointer(3, gl.GL_FLOAT, 48, _texcoords) gl.glTexEnvi(gl.GL_TEXTURE_ENV, gl.GL_TEXTURE_ENV_MODE, gl.GL_MODULATE) self._colormap._enable() _unit += 1 # #################################### # # render the glowmap # if self._glowmap is not None : gl.glActiveTexture(_texunits[_unit]) gl.glClientActiveTexture(_texunits[_unit]) gl.glEnableClientState(gl.GL_TEXTURE_COORD_ARRAY) gl.glTexCoordPointer(3, gl.GL_FLOAT, 48, _texcoords) gl.glTexEnvi(gl.GL_TEXTURE_ENV, gl.GL_TEXTURE_ENV_MODE, gl.GL_ADD) gl.glEnable(gl.GL_BLEND) gl.glBlendFunc(gl.GL_ONE, gl.GL_ONE) self._glowmap._enable() _unit += 1 # #################################### # # return 1 # return 1 # ###################################### # # disable textures from last pass # else : if _bump : ################################## # # disable bump-blending # gl.glDisable(gl.GL_BLEND) gl.glDisable(gl.GL_POLYGON_OFFSET_FILL) gl.glPolygonOffset(0,0) # #################################### # _unit = 0 if self._colormap is not None : gl.glActiveTexture(_texunits[_unit]) self._colormap._disable() _unit += 1 if self._glowmap is not None : gl.glActiveTexture(_texunits[_unit]) self._glowmap._disable() return 0 # ######################################