/* -*-c++-*- * Copyright (C) 2017 Julien Valentin * * This library is open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or * (at your option) any later version. The full license is in LICENSE file * included with this distribution, and on the openscenegraph.org website. * * This library 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 * OpenSceneGraph Public License for more details. */ #include #include #ifndef GL_TEXTURE_MIN_LOD #define GL_TEXTURE_MIN_LOD 0x813A #endif #ifndef GL_TEXTURE_MAX_LOD #define GL_TEXTURE_MAX_LOD 0x813B #endif #ifndef GL_TEXTURE_WRAP_R #define GL_TEXTURE_WRAP_R 0x2804 #endif using namespace osg; Sampler::Sampler(): StateAttribute(), _wrap_s(Texture::CLAMP), _wrap_t(Texture::CLAMP), _wrap_r(Texture::CLAMP), _shadow_compare_func(Texture::LEQUAL), _shadow_texture_mode(Texture::NONE), _min_filter(Texture::LINEAR_MIPMAP_LINEAR), // trilinear _mag_filter(Texture::LINEAR), _maxAnisotropy(1.0f), _minlod(0.0f), _maxlod(-1.0f), _lodbias(0.0f) { _PCdirtyflags.setAllElementsTo(true); _PCsampler.setAllElementsTo(0); } Sampler::Sampler(const Sampler& sampler,const CopyOp ©op ):StateAttribute(sampler,copyop), _wrap_s(sampler._wrap_s), _wrap_t(sampler._wrap_t), _wrap_r(sampler._wrap_r), _shadow_compare_func(sampler._shadow_compare_func), _shadow_texture_mode(sampler._shadow_texture_mode), _min_filter(sampler._min_filter), _mag_filter(sampler._mag_filter), _maxAnisotropy(sampler._maxAnisotropy), _minlod(sampler._minlod), _maxlod(sampler._maxlod), _lodbias(sampler._lodbias) { _PCdirtyflags.setAllElementsTo(true); _PCsampler.setAllElementsTo(0); } void Sampler::setWrap(Texture::WrapParameter which, Texture::WrapMode wrap) { switch( which ) { case Texture::WRAP_S : _wrap_s = wrap; _PCdirtyflags.setAllElementsTo(true); break; case Texture::WRAP_T : _wrap_t = wrap; _PCdirtyflags.setAllElementsTo(true); break; case Texture::WRAP_R : _wrap_r = wrap; _PCdirtyflags.setAllElementsTo(true); break; default : OSG_WARN<<"Error: invalid 'which' passed Sampler::setWrap("<<(unsigned int)which<<","<<(unsigned int)wrap<<")"<(); GLuint samplerobject = _PCsampler[contextID]; if(samplerobject==0) { extensions->glGenSamplers(1,&_PCsampler[contextID]); samplerobject = _PCsampler[contextID]; } Texture::WrapMode ws = _wrap_s, wt = _wrap_t, wr = _wrap_r; // GL_IBM_texture_mirrored_repeat, fall-back REPEAT if (!extensions->isTextureMirroredRepeatSupported) { if (ws == Texture::MIRROR) ws = Texture::REPEAT; if (wt == Texture::MIRROR) wt = Texture::REPEAT; if (wr == Texture::MIRROR) wr = Texture::REPEAT; } // GL_EXT_texture_edge_clamp, fall-back CLAMP if (!extensions->isTextureEdgeClampSupported) { if (ws == Texture::CLAMP_TO_EDGE) ws = Texture::CLAMP; if (wt == Texture::CLAMP_TO_EDGE) wt = Texture::CLAMP; if (wr == Texture::CLAMP_TO_EDGE) wr = Texture::CLAMP; } if(!extensions->isTextureBorderClampSupported) { if(ws == Texture::CLAMP_TO_BORDER) ws = Texture::CLAMP; if(wt == Texture::CLAMP_TO_BORDER) wt = Texture::CLAMP; if(wr == Texture::CLAMP_TO_BORDER) wr = Texture::CLAMP; } #if defined(OSG_GLES1_AVAILABLE) || defined(OSG_GLES2_AVAILABLE) || defined(OSG_GL3_AVAILABLE) if (ws == Texture::CLAMP) ws = Texture::CLAMP_TO_EDGE; if (wt == Texture::CLAMP) wt = Texture::CLAMP_TO_EDGE; if (wr == Texture::CLAMP) wr = Texture::CLAMP_TO_EDGE; #endif extensions->glSamplerParameteri( samplerobject, GL_TEXTURE_WRAP_S, ws ); extensions->glSamplerParameteri( samplerobject, GL_TEXTURE_WRAP_T, wt ); extensions->glSamplerParameteri( samplerobject, GL_TEXTURE_WRAP_R, wr ); extensions->glSamplerParameteri( samplerobject, GL_TEXTURE_MIN_FILTER, _min_filter); extensions->glSamplerParameteri( samplerobject, GL_TEXTURE_MAG_FILTER, _mag_filter); if (extensions->isTextureBorderClampSupported) { #ifndef GL_TEXTURE_BORDER_COLOR #define GL_TEXTURE_BORDER_COLOR 0x1004 #endif GLfloat color[4] = {(GLfloat)_borderColor.r(), (GLfloat)_borderColor.g(), (GLfloat)_borderColor.b(), (GLfloat)_borderColor.a()}; extensions->glSamplerParameterfv(samplerobject, GL_TEXTURE_BORDER_COLOR, color); } extensions->glSamplerParameteri(samplerobject, GL_TEXTURE_COMPARE_MODE, _shadow_texture_mode); extensions->glSamplerParameteri(samplerobject, GL_TEXTURE_COMPARE_FUNC, _shadow_compare_func); if (extensions->isTextureFilterAnisotropicSupported) { // note, GL_TEXTURE_MAX_ANISOTROPY_EXT will either be defined // by gl.h (or via glext.h) or by include/osg/Texture. extensions->glSamplerParameterf(samplerobject, GL_TEXTURE_MAX_ANISOTROPY_EXT, _maxAnisotropy); } if(_maxlod - _minlod > 0) { // if range is valid extensions->glSamplerParameterf(samplerobject, GL_TEXTURE_MIN_LOD, _minlod); extensions->glSamplerParameterf(samplerobject, GL_TEXTURE_MAX_LOD, _maxlod); } extensions->glSamplerParameterf(samplerobject, GL_TEXTURE_LOD_BIAS, _lodbias); _PCdirtyflags[contextID]=false; } } /** bind SamplerObject **/ void Sampler::apply(State&state) const { unsigned int contextID = state.getContextID(); if( _PCdirtyflags[contextID] ) compileGLObjects(state); state.get()->glBindSampler( state.getActiveTextureUnit(), _PCsampler[contextID] ); } void Sampler::releaseGLObjects(State* state) const { if(state) { unsigned int contextID=state->getContextID(); state->get()->glDeleteSamplers(1,&_PCsampler[contextID]); } } int Sampler::compare(const StateAttribute& sa) const { COMPARE_StateAttribute_Types(Sampler,sa) COMPARE_StateAttribute_Parameter(_wrap_t) COMPARE_StateAttribute_Parameter(_wrap_r) COMPARE_StateAttribute_Parameter(_min_filter) COMPARE_StateAttribute_Parameter(_mag_filter) COMPARE_StateAttribute_Parameter(_shadow_compare_func) COMPARE_StateAttribute_Parameter(_shadow_texture_mode) COMPARE_StateAttribute_Parameter(_maxAnisotropy) COMPARE_StateAttribute_Parameter(_minlod) COMPARE_StateAttribute_Parameter(_maxlod) COMPARE_StateAttribute_Parameter(_lodbias) return 0; // passed all the above comparison macros, must be equal. }