X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=simgear%2Fscene%2Fmaterial%2FTextureBuilder.cxx;h=f81f2b9bfaedb42eb035a9b9e0718a5560f35358;hb=d04cf4d8978866eb80a1639b6d4ddfe387338c77;hp=9103fe59ba099934f8512333da6acecbe631d05a;hpb=14e5e87a4d4f62f2fac873f5cee856b561f8568a;p=simgear.git diff --git a/simgear/scene/material/TextureBuilder.cxx b/simgear/scene/material/TextureBuilder.cxx index 9103fe59..f81f2b9b 100644 --- a/simgear/scene/material/TextureBuilder.cxx +++ b/simgear/scene/material/TextureBuilder.cxx @@ -20,15 +20,22 @@ #include "TextureBuilder.hxx" +#include "Pass.hxx" + +#include +#include +#include #include #include #include #include #include +#include #include #include +#include #include #include #include @@ -43,10 +50,14 @@ using namespace osg; using namespace effect; +TexEnvCombine* buildTexEnvCombine(Effect* effect, + const SGPropertyNode* envProp); +TexGen* buildTexGen(Effect* Effect, const SGPropertyNode* tgenProp); + // Hack to force inclusion of TextureBuilder.cxx in library osg::Texture* TextureBuilder::buildFromType(Effect* effect, const string& type, const SGPropertyNode*props, - const osgDB::ReaderWriter::Options* + const SGReaderWriterXMLOptions* options) { return EffectBuilder::buildFromType(effect, type, props, options); @@ -56,6 +67,92 @@ typedef boost::tuple TexTuple; +EffectNameValue texEnvModesInit[] = +{ + {"add", TexEnv::ADD}, + {"blend", TexEnv::BLEND}, + {"decal", TexEnv::DECAL}, + {"modulate", TexEnv::MODULATE}, + {"replace", TexEnv::REPLACE} +}; +EffectPropertyMap texEnvModes(texEnvModesInit); + +TexEnv* buildTexEnv(Effect* effect, const SGPropertyNode* prop) +{ + const SGPropertyNode* modeProp = getEffectPropertyChild(effect, prop, + "mode"); + const SGPropertyNode* colorProp = getEffectPropertyChild(effect, prop, + "color"); + if (!modeProp) + return 0; + TexEnv::Mode mode = TexEnv::MODULATE; + findAttr(texEnvModes, modeProp, mode); + if (mode == TexEnv::MODULATE) { + return StateAttributeFactory::instance()->getStandardTexEnv(); + } + TexEnv* env = new TexEnv(mode); + if (colorProp) + env->setColor(toOsg(colorProp->getValue())); + return env; + } + + +void TextureUnitBuilder::buildAttribute(Effect* effect, Pass* pass, + const SGPropertyNode* prop, + const SGReaderWriterXMLOptions* options) +{ + if (!isAttributeActive(effect, prop)) + return; + // Decode the texture unit + int unit = 0; + const SGPropertyNode* pUnit = prop->getChild("unit"); + if (pUnit) { + unit = pUnit->getValue(); + } else { + const SGPropertyNode* pName = prop->getChild("name"); + if (pName) + try { + unit = boost::lexical_cast(pName->getStringValue()); + } catch (boost::bad_lexical_cast& lex) { + SG_LOG(SG_INPUT, SG_ALERT, "can't decode name as texture unit " + << lex.what()); + } + } + const SGPropertyNode* pType = getEffectPropertyChild(effect, prop, "type"); + string type; + if (!pType) + type = "2d"; + else + type = pType->getStringValue(); + Texture* texture = 0; + try { + texture = TextureBuilder::buildFromType(effect, type, prop, + options); + } + catch (BuilderException& e) { + SG_LOG(SG_INPUT, SG_ALERT, "No image file for texture, using white "); + texture = StateAttributeFactory::instance()->getWhiteTexture(); + } + pass->setTextureAttributeAndModes(unit, texture); + const SGPropertyNode* envProp = prop->getChild("environment"); + if (envProp) { + TexEnv* env = buildTexEnv(effect, envProp); + if (env) + pass->setTextureAttributeAndModes(unit, env); + } + const SGPropertyNode* combineProp = prop->getChild("texenv-combine"); + TexEnvCombine* combiner = 0; + if (combineProp && ((combiner = buildTexEnvCombine(effect, combineProp)))) + pass->setTextureAttributeAndModes(unit, combiner); + const SGPropertyNode* tgenProp = prop->getChild("texgen"); + TexGen* tgen = 0; + if (tgenProp && (tgen = buildTexGen(effect, tgenProp))) + pass->setTextureAttributeAndModes(unit, tgen); +} + +// InstallAttributeBuilder call is in Effect.cxx to force this file to +// be linked in. + namespace { EffectNameValue filterModesInit[] = @@ -81,28 +178,31 @@ EffectPropertyMap wrapModes(wrapModesInit); TexTuple makeTexTuple(Effect* effect, const SGPropertyNode* props, - const osgDB::ReaderWriter::Options* options, + const SGReaderWriterXMLOptions* options, const string& texType) { Texture::FilterMode minFilter = Texture::LINEAR_MIPMAP_LINEAR; - findAttr(filterModes, getEffectPropertyChild(effect, props, "filter"), - minFilter); + const SGPropertyNode* ep = 0; + if ((ep = getEffectPropertyChild(effect, props, "filter"))) + findAttr(filterModes, ep, minFilter); Texture::FilterMode magFilter = Texture::LINEAR; - findAttr(filterModes, getEffectPropertyChild(effect, props, - "mag-filter"), - magFilter); + if ((ep = getEffectPropertyChild(effect, props, "mag-filter"))) + findAttr(filterModes, ep, magFilter); const SGPropertyNode* pWrapS = getEffectPropertyChild(effect, props, "wrap-s"); Texture::WrapMode sWrap = Texture::CLAMP; - findAttr(wrapModes, pWrapS, sWrap); + if (pWrapS) + findAttr(wrapModes, pWrapS, sWrap); const SGPropertyNode* pWrapT = getEffectPropertyChild(effect, props, "wrap-t"); Texture::WrapMode tWrap = Texture::CLAMP; - findAttr(wrapModes, pWrapT, tWrap); + if (pWrapT) + findAttr(wrapModes, pWrapT, tWrap); const SGPropertyNode* pWrapR = getEffectPropertyChild(effect, props, "wrap-r"); Texture::WrapMode rWrap = Texture::CLAMP; - findAttr(wrapModes, pWrapR, rWrap); + if (pWrapR) + findAttr(wrapModes, pWrapR, rWrap); const SGPropertyNode* pImage = getEffectPropertyChild(effect, props, "image"); string imageName; @@ -114,7 +214,7 @@ TexTuple makeTexTuple(Effect* effect, const SGPropertyNode* props, } void setAttrs(const TexTuple& attrs, Texture* tex, - const osgDB::ReaderWriter::Options* options) + const SGReaderWriterXMLOptions* options) { const string& imageName = attrs.get<0>(); if (imageName.empty()) { @@ -154,7 +254,7 @@ class TexBuilder : public TextureBuilder public: TexBuilder(const string& texType) : _type(texType) {} Texture* build(Effect* effect, const SGPropertyNode*, - const osgDB::ReaderWriter::Options* options); + const SGReaderWriterXMLOptions* options); protected: typedef map > TexMap; TexMap texMap; @@ -163,7 +263,7 @@ protected: template Texture* TexBuilder::build(Effect* effect, const SGPropertyNode* props, - const osgDB::ReaderWriter::Options* options) + const SGReaderWriterXMLOptions* options) { TexTuple attrs = makeTexTuple(effect, props, options, _type); typename TexMap::iterator itr = texMap.find(attrs); @@ -187,11 +287,11 @@ class WhiteTextureBuilder : public TextureBuilder { public: Texture* build(Effect* effect, const SGPropertyNode*, - const osgDB::ReaderWriter::Options* options); + const SGReaderWriterXMLOptions* options); }; Texture* WhiteTextureBuilder::build(Effect* effect, const SGPropertyNode*, - const osgDB::ReaderWriter::Options* options) + const SGReaderWriterXMLOptions* options) { return StateAttributeFactory::instance()->getWhiteTexture(); } @@ -201,6 +301,25 @@ namespace TextureBuilder::Registrar installWhite("white", new WhiteTextureBuilder); } +class TransparentTextureBuilder : public TextureBuilder +{ +public: + Texture* build(Effect* effect, const SGPropertyNode*, + const SGReaderWriterXMLOptions* options); +}; + +Texture* TransparentTextureBuilder::build(Effect* effect, const SGPropertyNode*, + const SGReaderWriterXMLOptions* options) +{ + return StateAttributeFactory::instance()->getTransparentTexture(); +} + +namespace +{ +TextureBuilder::Registrar installTransparent("transparent", + new TransparentTextureBuilder); +} + osg::Image* make3DNoiseImage(int texSize) { osg::Image* image = new osg::Image; @@ -250,14 +369,14 @@ class NoiseBuilder : public TextureBuilder { public: Texture* build(Effect* effect, const SGPropertyNode*, - const osgDB::ReaderWriter::Options* options); + const SGReaderWriterXMLOptions* options); protected: typedef map > NoiseMap; NoiseMap _noises; }; Texture* NoiseBuilder::build(Effect* effect, const SGPropertyNode* props, - const osgDB::ReaderWriter::Options* options) + const SGReaderWriterXMLOptions* options) { int texSize = 64; const SGPropertyNode* sizeProp = getEffectPropertyChild(effect, props, @@ -283,22 +402,224 @@ namespace TextureBuilder::Registrar installNoise("noise", new NoiseBuilder); } +EffectNameValue combineParamInit[] = +{ + {"replace", TexEnvCombine::REPLACE}, + {"modulate", TexEnvCombine::MODULATE}, + {"add", TexEnvCombine::ADD}, + {"add-signed", TexEnvCombine::ADD_SIGNED}, + {"interpolate", TexEnvCombine::INTERPOLATE}, + {"subtract", TexEnvCombine::SUBTRACT}, + {"dot3-rgb", TexEnvCombine::DOT3_RGB}, + {"dot3-rgba", TexEnvCombine::DOT3_RGBA} +}; + +EffectPropertyMap combineParams(combineParamInit); + +EffectNameValue sourceParamInit[] = +{ + {"constant", TexEnvCombine::CONSTANT}, + {"primary_color", TexEnvCombine::PRIMARY_COLOR}, + {"previous", TexEnvCombine::PREVIOUS}, + {"texture", TexEnvCombine::TEXTURE}, + {"texture0", TexEnvCombine::TEXTURE0}, + {"texture1", TexEnvCombine::TEXTURE1}, + {"texture2", TexEnvCombine::TEXTURE2}, + {"texture3", TexEnvCombine::TEXTURE3}, + {"texture4", TexEnvCombine::TEXTURE4}, + {"texture5", TexEnvCombine::TEXTURE5}, + {"texture6", TexEnvCombine::TEXTURE6}, + {"texture7", TexEnvCombine::TEXTURE7} +}; + +EffectPropertyMap sourceParams(sourceParamInit); + +EffectNameValue opParamInit[] = +{ + {"src-color", TexEnvCombine::SRC_COLOR}, + {"one-minus-src-color", TexEnvCombine::ONE_MINUS_SRC_COLOR}, + {"src-alpha", TexEnvCombine::SRC_ALPHA}, + {"one-minus-src-alpha", TexEnvCombine::ONE_MINUS_SRC_ALPHA} +}; + +EffectPropertyMap operandParams(opParamInit); + +TexEnvCombine* buildTexEnvCombine(Effect* effect, const SGPropertyNode* envProp) +{ + if (!isAttributeActive(effect, envProp)) + return 0; + TexEnvCombine* result = new TexEnvCombine; + const SGPropertyNode* p = 0; + if ((p = getEffectPropertyChild(effect, envProp, "combine-rgb"))) { + TexEnvCombine::CombineParam crgb = TexEnvCombine::MODULATE; + findAttr(combineParams, p, crgb); + result->setCombine_RGB(crgb); + } + if ((p = getEffectPropertyChild(effect, envProp, "combine-alpha"))) { + TexEnvCombine::CombineParam calpha = TexEnvCombine::MODULATE; + findAttr(combineParams, p, calpha); + result->setCombine_Alpha(calpha); + } + if ((p = getEffectPropertyChild(effect, envProp, "source0-rgb"))) { + TexEnvCombine::SourceParam source = TexEnvCombine::TEXTURE; + findAttr(sourceParams, p, source); + result->setSource0_RGB(source); + } + if ((p = getEffectPropertyChild(effect, envProp, "source1-rgb"))) { + TexEnvCombine::SourceParam source = TexEnvCombine::PREVIOUS; + findAttr(sourceParams, p, source); + result->setSource1_RGB(source); + } + if ((p = getEffectPropertyChild(effect, envProp, "source2-rgb"))) { + TexEnvCombine::SourceParam source = TexEnvCombine::CONSTANT; + findAttr(sourceParams, p, source); + result->setSource2_RGB(source); + } + if ((p = getEffectPropertyChild(effect, envProp, "source0-alpha"))) { + TexEnvCombine::SourceParam source = TexEnvCombine::TEXTURE; + findAttr(sourceParams, p, source); + result->setSource0_Alpha(source); + } + if ((p = getEffectPropertyChild(effect, envProp, "source1-alpha"))) { + TexEnvCombine::SourceParam source = TexEnvCombine::PREVIOUS; + findAttr(sourceParams, p, source); + result->setSource1_Alpha(source); + } + if ((p = getEffectPropertyChild(effect, envProp, "source2-alpha"))) { + TexEnvCombine::SourceParam source = TexEnvCombine::CONSTANT; + findAttr(sourceParams, p, source); + result->setSource2_Alpha(source); + } + if ((p = getEffectPropertyChild(effect, envProp, "operand0-rgb"))) { + TexEnvCombine::OperandParam op = TexEnvCombine::SRC_COLOR; + findAttr(operandParams, p, op); + result->setOperand0_RGB(op); + } + if ((p = getEffectPropertyChild(effect, envProp, "operand1-rgb"))) { + TexEnvCombine::OperandParam op = TexEnvCombine::SRC_COLOR; + findAttr(operandParams, p, op); + result->setOperand1_RGB(op); + } + if ((p = getEffectPropertyChild(effect, envProp, "operand2-rgb"))) { + TexEnvCombine::OperandParam op = TexEnvCombine::SRC_ALPHA; + findAttr(operandParams, p, op); + result->setOperand2_RGB(op); + } + if ((p = getEffectPropertyChild(effect, envProp, "operand0-alpha"))) { + TexEnvCombine::OperandParam op = TexEnvCombine::SRC_ALPHA; + findAttr(operandParams, p, op); + result->setOperand0_Alpha(op); + } + if ((p = getEffectPropertyChild(effect, envProp, "operand1-alpha"))) { + TexEnvCombine::OperandParam op = TexEnvCombine::SRC_ALPHA; + findAttr(operandParams, p, op); + result->setOperand1_Alpha(op); + } + if ((p = getEffectPropertyChild(effect, envProp, "operand2-alpha"))) { + TexEnvCombine::OperandParam op = TexEnvCombine::SRC_ALPHA; + findAttr(operandParams, p, op); + result->setOperand2_Alpha(op); + } + if ((p = getEffectPropertyChild(effect, envProp, "scale-rgb"))) { + result->setScale_RGB(p->getValue()); + } + if ((p = getEffectPropertyChild(effect, envProp, "scale-alpha"))) { + result->setScale_Alpha(p->getValue()); + } +#if 0 + if ((p = getEffectPropertyChild(effect, envProp, "constant-color"))) { + SGVec4d color = p->getValue(); + result->setConstantColor(toOsg(color)); + } else if ((p = getEffectPropertyChild(effect, envProp, + "light-direction"))) { + SGVec3d direction = p->getValue(); + result->setConstantColorAsLightDirection(toOsg(direction)); + } +#endif + const SGPropertyNode* colorNode = envProp->getChild("constant-color"); + if (colorNode) + initFromParameters(effect, colorNode, result, + &TexEnvCombine::setConstantColor, colorFields); + return result; +} + +EffectNameValue tgenModeInit[] = +{ + { "object-linear", TexGen::OBJECT_LINEAR}, + { "eye-linear", TexGen::EYE_LINEAR}, + { "sphere-map", TexGen::SPHERE_MAP}, + { "normal-map", TexGen::NORMAL_MAP}, + { "reflection-map", TexGen::REFLECTION_MAP} +}; + +EffectPropertyMap tgenModes(tgenModeInit); + +EffectNameValue tgenCoordInit[] = +{ + {"s", TexGen::S}, + {"t", TexGen::T}, + {"r", TexGen::R}, + {"q", TexGen::Q} +}; + +EffectPropertyMap tgenCoords(tgenCoordInit); + +TexGen* buildTexGen(Effect* effect, const SGPropertyNode* tgenProp) +{ + if (!isAttributeActive(effect, tgenProp)) + return 0; + TexGen* result = new TexGen; + const SGPropertyNode* p = 0; + TexGen::Mode mode = TexGen::OBJECT_LINEAR; + findAttr(tgenModes, getEffectPropertyChild(effect, tgenProp, "mode"), mode); + result->setMode(mode); + const SGPropertyNode* planesNode = tgenProp->getChild("planes"); + if (planesNode) { + for (int i = 0; i < planesNode->nChildren(); ++i) { + const SGPropertyNode* planeNode = planesNode->getChild(i); + TexGen::Coord coord; + findAttr(tgenCoords, planeNode->getName(), coord); + const SGPropertyNode* realNode + = getEffectPropertyNode(effect, planeNode); + SGVec4d plane = realNode->getValue(); + result->setPlane(coord, toOsg(plane)); + } + } + return result; +} + bool makeTextureParameters(SGPropertyNode* paramRoot, const StateSet* ss) { + SGPropertyNode* texUnit = makeChild(paramRoot, "texture"); const Texture* tex = getStateAttribute(0, ss); const Texture2D* texture = dynamic_cast(tex); - if (!tex) + makeChild(texUnit, "unit")->setValue(0); + if (!tex) { + // The default shader-based technique ignores active + makeChild(texUnit, "active")->setValue(false); return false; + } const Image* image = texture->getImage(); string imageName; - if (image) + if (image) { imageName = image->getFileName(); + } else { + makeChild(texUnit, "active")->setValue(false); + makeChild(texUnit, "type")->setValue("white"); + return false; + } + makeChild(texUnit, "active")->setValue(true); + makeChild(texUnit, "type")->setValue("2d"); + string filter = findName(filterModes, + texture->getFilter(Texture::MIN_FILTER)); + string magFilter = findName(filterModes, + texture->getFilter(Texture::MAG_FILTER)); string wrapS = findName(wrapModes, texture->getWrap(Texture::WRAP_S)); string wrapT = findName(wrapModes, texture->getWrap(Texture::WRAP_T)); string wrapR = findName(wrapModes, texture->getWrap(Texture::WRAP_R)); - SGPropertyNode* texUnit = makeChild(paramRoot, "texture-unit"); - makeChild(texUnit, "unit")->setValue(0); makeChild(texUnit, "image")->setStringValue(imageName); + makeChild(texUnit, "filter")->setStringValue(filter); + makeChild(texUnit, "mag-filter")->setStringValue(magFilter); makeChild(texUnit, "wrap-s")->setStringValue(wrapS); makeChild(texUnit, "wrap-t")->setStringValue(wrapT); makeChild(texUnit, "wrap-r")->setStringValue(wrapR);