/* backpropagtation algorithm */ void Backpropagation (int* input, int* targetOutput) { int i = 0; float **hiddenDelta, *outputDelta; /* allocate output, hiddendelta and outputdelta */ hiddenDelta = (float **)calloc(numHiddenLayers, sizeof(float *)); outputDelta = (float *)calloc(numOutputNodes, sizeof(float)); for(i = 0; i < numHiddenLayers; i++) { hiddenDelta[i] = (float *)calloc(neuronsPerLayer, sizeof(float)); } ForwardPropagation (input, outputOutputs); CalcDelta(targetOutput, hiddenDelta, outputDelta); UpdateNetwork(hiddenDelta, outputDelta, input); for(i = 0; i < numHiddenLayers; i++) { free(hiddenDelta[i]); } free(hiddenDelta); free(outputDelta); return; }
sRGBfloat cRenderWorker::TextureShader( const sShaderInputData &input, cMaterial::enumTextureSelection texSelect, cMaterial *mat) const { cObjectData objectData = data->objectData[input.objectId]; double texturePixelSize = 1.0; CVector3 textureVectorX, textureVectorY; CVector2<double> texPoint = TextureMapping(input.point, input.normal, objectData, mat, &textureVectorX, &textureVectorY) + CVector2<double>(0.5, 0.5); // mipmapping - calculation of texture pixel size double delta = CalcDelta(input.point); double deltaTexX = ((TextureMapping(input.point + textureVectorX * delta, input.normal, objectData, mat) + CVector2<double>(0.5, 0.5)) - texPoint) .Length(); double deltaTexY = ((TextureMapping(input.point + textureVectorY * delta, input.normal, objectData, mat) + CVector2<double>(0.5, 0.5)) - texPoint) .Length(); if (deltaTexX > 0.5) deltaTexX = 1.0 - deltaTexX; if (deltaTexY > 0.5) deltaTexY = 1.0 - deltaTexY; deltaTexX = deltaTexX / fabs(input.viewVector.Dot(input.normal)); deltaTexY = deltaTexY / fabs(input.viewVector.Dot(input.normal)); texturePixelSize = 1.0 / max(deltaTexX, deltaTexY); sRGBfloat tex; switch (texSelect) { case cMaterial::texColor: { tex = input.material->colorTexture.Pixel(texPoint, texturePixelSize); break; } case cMaterial::texDiffuse: { tex = input.material->diffusionTexture.Pixel(texPoint, texturePixelSize); break; } case cMaterial::texLuminosity: { tex = input.material->luminosityTexture.Pixel(texPoint, texturePixelSize); break; } case cMaterial::texDisplacement: { tex = input.material->displacementTexture.Pixel(texPoint, texturePixelSize); break; } } return sRGBfloat(tex.R, tex.G, tex.B); }
CVector3 cRenderWorker::NormalMapShader(const sShaderInputData &input) { cObjectData objectData = data->objectData[input.objectId]; CVector3 texX, texY; double texturePixelSize = 1.0; CVector2<double> texPoint = TextureMapping(input.point, input.normal, objectData, input.material, &texX, &texY) + CVector2<double>(0.5, 0.5); // mipmapping - calculation of texture pixel size double delta = CalcDelta(input.point); double deltaTexX = ((TextureMapping(input.point + texX * delta, input.normal, objectData, input.material) + CVector2<double>(0.5, 0.5)) - texPoint) .Length(); double deltaTexY = ((TextureMapping(input.point + texY * delta, input.normal, objectData, input.material) + CVector2<double>(0.5, 0.5)) - texPoint) .Length(); deltaTexX = deltaTexX / fabs(input.viewVector.Dot(input.normal)); deltaTexY = deltaTexY / fabs(input.viewVector.Dot(input.normal)); texturePixelSize = 1.0 / max(deltaTexX, deltaTexY); CVector3 n = input.normal; // tangent vectors: CVector3 t = n.Cross(texX); t.Normalize(); CVector3 b = n.Cross(texY); b.Normalize(); CMatrix33 tbn(b, t, n); CVector3 tex; if (input.material->normalMapTextureFromBumpmap) { tex = input.material->normalMapTexture.NormalMapFromBumpMap( texPoint, input.material->normalMapTextureHeight, texturePixelSize); } else { tex = input.material->normalMapTexture.NormalMap( texPoint, input.material->normalMapTextureHeight, texturePixelSize); } CVector3 result = tbn * tex; result.Normalize(); return result; }
sRGBAfloat cRenderWorker::VolumetricShader( const sShaderInputData &input, sRGBAfloat oldPixel, sRGBAfloat *opacityOut) { sRGBAfloat output; float totalOpacity = 0.0; output.R = oldPixel.R; output.G = oldPixel.G; output.B = oldPixel.B; output.A = oldPixel.A; // volumetric fog init double colourThresh = params->volFogColour1Distance; double colourThresh2 = params->volFogColour2Distance; double fogReduce = params->volFogDistanceFactor; double fogIntensity = params->volFogDensity; // visible lights init int numberOfLights = data->lights.GetNumberOfLights(); if (numberOfLights < 4) numberOfLights = 4; // glow init double glow = input.stepCount * params->glowIntensity / 512.0 * params->DEFactor; double glowN = 1.0 - glow; if (glowN < 0.0) glowN = 0.0; double glowR = (params->glowColor1.R * glowN + params->glowColor2.R * glow) / 65536.0; double glowG = (params->glowColor1.G * glowN + params->glowColor2.G * glow) / 65536.0; double glowB = (params->glowColor1.B * glowN + params->glowColor2.B * glow) / 65536.0; double totalStep = 0.0; // qDebug() << "Start volumetric shader &&&&&&&&&&&&&&&&&&&&"; sShaderInputData input2 = input; for (int index = input.stepCount - 1; index > 0; index--) { double step = input.stepBuff[index].step; double distance = input.stepBuff[index].distance; CVector3 point = input.stepBuff[index].point; totalStep += step; input2.point = point; input2.distThresh = input.stepBuff[index].distThresh; // qDebug() << "i" << index << "dist" << distance << "iters" << input.stepBuff[index].iters << // "distThresh" << input2.distThresh << "step" << step << "point" << point.Debug(); if (totalStep < CalcDelta(point)) { continue; } step = totalStep; totalStep = 0.0; //------------------- glow if (params->glowEnabled) { double glowOpacity = glow / input.stepCount; if (glowOpacity > 1.0) glowOpacity = 1.0; output.R = glowOpacity * glowR + (1.0 - glowOpacity) * output.R; output.G = glowOpacity * glowG + (1.0 - glowOpacity) * output.G; output.B = glowOpacity * glowB + (1.0 - glowOpacity) * output.B; output.A += glowOpacity; } // qDebug() << "step" << step; //------------------ visible light if (params->auxLightVisibility > 0) { double miniStep = 0.0; double lastMiniSteps = -1.0; for (double miniSteps = 0.0; miniSteps < step; miniSteps += miniStep) { double lowestLightSize = 1e10; double lowestLightDist = 1e10; for (int i = 0; i < numberOfLights; ++i) { const cLights::sLight *light = data->lights.GetLight(i); if (light->enabled) { CVector3 lightDistVect = (point - input.viewVector * miniSteps) - light->position; double lightDist = lightDistVect.Length(); double lightSize = sqrt(light->intensity) * params->auxLightVisibilitySize; double distToLightSurface = lightDist - lightSize; if (distToLightSurface < 0.0) distToLightSurface = 0.0; if (distToLightSurface <= lowestLightDist) { if (lightSize < lowestLightSize) { lowestLightSize = lightSize; } lowestLightDist = distToLightSurface; } } } miniStep = 0.1 * (lowestLightDist + 0.1 * lowestLightSize); if (miniStep > step - miniSteps) miniStep = step - miniSteps; // qDebug() << "lowDist:" << lowestLightDist << "lowSize" << lowestLightSize << "miniStep" // << miniStep; for (int i = 0; i < numberOfLights; ++i) { const cLights::sLight *light = data->lights.GetLight(i); if (light->enabled) { CVector3 lightDistVect = (point - input.viewVector * miniSteps) - light->position; double lightDist = lightDistVect.Length(); double lightSize = sqrt(light->intensity) * params->auxLightVisibilitySize; double r2 = lightDist / lightSize; double bellFunction = 1.0 / (1.0 + pow(r2, 4.0)); double lightDensity = miniStep * bellFunction * params->auxLightVisibility / lightSize; output.R += lightDensity * light->colour.R / 65536.0; output.G += lightDensity * light->colour.G / 65536.0; output.B += lightDensity * light->colour.B / 65536.0; output.A += lightDensity; } } if (miniSteps == lastMiniSteps) { // qWarning() << "Dead computation\n" // << "\npoint:" << (point - input.viewVector * miniSteps).Debug(); break; } lastMiniSteps = miniSteps; } } // fake lights (orbit trap) if (params->fakeLightsEnabled) { sFractalIn fractIn(point, params->minN, params->N, params->common, -1); sFractalOut fractOut; Compute<fractal::calcModeOrbitTrap>(*fractal, fractIn, &fractOut); double r = fractOut.orbitTrapR; r = sqrt(1.0f / (r + 1.0e-30f)); double fakeLight = 1.0 / (pow(r, 10.0 / params->fakeLightsVisibilitySize) * pow(10.0, 10.0 / params->fakeLightsVisibilitySize) + 1e-100); output.R += fakeLight * step * params->fakeLightsVisibility; output.G += fakeLight * step * params->fakeLightsVisibility; output.B += fakeLight * step * params->fakeLightsVisibility; output.A += fakeLight * step * params->fakeLightsVisibility; } //---------------------- volumetric lights with shadows in fog for (int i = 0; i < 5; i++) { if (i == 0 && params->volumetricLightEnabled[0]) { sRGBAfloat shadowOutputTemp = MainShadow(input2); output.R += shadowOutputTemp.R * step * params->volumetricLightIntensity[0] * params->mainLightColour.R / 65536.0; output.G += shadowOutputTemp.G * step * params->volumetricLightIntensity[0] * params->mainLightColour.G / 65536.0; output.B += shadowOutputTemp.B * step * params->volumetricLightIntensity[0] * params->mainLightColour.B / 65536.0; output.A += (shadowOutputTemp.R + shadowOutputTemp.G + shadowOutputTemp.B) / 3.0 * step * params->volumetricLightIntensity[0]; } if (i > 0) { const cLights::sLight *light = data->lights.GetLight(i - 1); if (light->enabled && params->volumetricLightEnabled[i]) { CVector3 lightVectorTemp = light->position - point; double distanceLight = lightVectorTemp.Length(); double distanceLight2 = distanceLight * distanceLight; lightVectorTemp.Normalize(); double lightShadow = AuxShadow(input2, distanceLight, lightVectorTemp); output.R += lightShadow * light->colour.R / 65536.0 * params->volumetricLightIntensity[i] * step / distanceLight2; output.G += lightShadow * light->colour.G / 65536.0 * params->volumetricLightIntensity[i] * step / distanceLight2; output.B += lightShadow * light->colour.B / 65536.0 * params->volumetricLightIntensity[i] * step / distanceLight2; output.A += lightShadow * params->volumetricLightIntensity[i] * step / distanceLight2; } } } //----------------------- basic fog if (params->fogEnabled) { double fogDensity = step / params->fogVisibility; if (fogDensity > 1.0) fogDensity = 1.0; output.R = fogDensity * params->fogColor.R / 65536.0 + (1.0 - fogDensity) * output.R; output.G = fogDensity * params->fogColor.G / 65536.0 + (1.0 - fogDensity) * output.G; output.B = fogDensity * params->fogColor.B / 65536.0 + (1.0 - fogDensity) * output.B; totalOpacity = fogDensity + (1.0 - fogDensity) * totalOpacity; output.A = fogDensity + (1.0 - fogDensity) * output.A; } //-------------------- volumetric fog if (fogIntensity > 0.0 && params->volFogEnabled) { double densityTemp = (step * fogReduce) / (distance * distance + fogReduce * fogReduce); double k = distance / colourThresh; if (k > 1) k = 1.0; double kn = 1.0 - k; double fogRtemp = (params->volFogColour1.R * kn + params->volFogColour2.R * k); double fogGtemp = (params->volFogColour1.G * kn + params->volFogColour2.G * k); double fogBtemp = (params->volFogColour1.B * kn + params->volFogColour2.B * k); double k2 = distance / colourThresh2 * k; if (k2 > 1) k2 = 1.0; kn = 1.0 - k2; fogRtemp = (fogRtemp * kn + params->volFogColour3.R * k2); fogGtemp = (fogGtemp * kn + params->volFogColour3.G * k2); fogBtemp = (fogBtemp * kn + params->volFogColour3.B * k2); double fogDensity = 0.3 * fogIntensity * densityTemp / (1.0 + fogIntensity * densityTemp); if (fogDensity > 1) fogDensity = 1.0; output.R = fogDensity * fogRtemp / 65536.0 + (1.0 - fogDensity) * output.R; output.G = fogDensity * fogGtemp / 65536.0 + (1.0 - fogDensity) * output.G; output.B = fogDensity * fogBtemp / 65536.0 + (1.0 - fogDensity) * output.B; // qDebug() << "densityTemp " << densityTemp << "k" << k << "k2" << k2 << "fogTempR" << // fogRtemp << "fogDensity" << fogDensity << "output.R" << output.R; totalOpacity = fogDensity + (1.0 - fogDensity) * totalOpacity; output.A = fogDensity + (1.0 - fogDensity) * output.A; } // iter fog if (params->iterFogEnabled) { int L = input.stepBuff[index].iters; double opacity = IterOpacity(step, L, params->N, params->iterFogOpacityTrim, params->iterFogOpacity); sRGBAfloat newColour(0.0, 0.0, 0.0, 0.0); if (opacity > 0) { // fog colour double iterFactor1 = (L - params->iterFogOpacityTrim) / (params->iterFogColor1Maxiter - params->iterFogOpacityTrim); double k = iterFactor1; if (k > 1.0) k = 1.0; if (k < 0.0) k = 0.0; double kn = 1.0 - k; double fogColR = (params->iterFogColour1.R * kn + params->iterFogColour2.R * k); double fogColG = (params->iterFogColour1.G * kn + params->iterFogColour2.G * k); double fogColB = (params->iterFogColour1.B * kn + params->iterFogColour2.B * k); double iterFactor2 = (L - params->iterFogColor1Maxiter) / (params->iterFogColor2Maxiter - params->iterFogColor1Maxiter); double k2 = iterFactor2; if (k2 < 0.0) k2 = 0.0; if (k2 > 1.0) k2 = 1.0; kn = 1.0 - k2; fogColR = (fogColR * kn + params->iterFogColour3.R * k2); fogColG = (fogColG * kn + params->iterFogColour3.G * k2); fogColB = (fogColB * kn + params->iterFogColour3.B * k2); //---- for (int i = 0; i < 5; i++) { if (i == 0) { if (params->mainLightEnable && params->mainLightIntensity > 0.0) { sRGBAfloat shadowOutputTemp = MainShadow(input2); newColour.R += shadowOutputTemp.R * params->mainLightColour.R / 65536.0 * params->mainLightIntensity; newColour.G += shadowOutputTemp.G * params->mainLightColour.G / 65536.0 * params->mainLightIntensity; newColour.B += shadowOutputTemp.B * params->mainLightColour.B / 65536.0 * params->mainLightIntensity; } } if (i > 0) { const cLights::sLight *light = data->lights.GetLight(i - 1); if (light->enabled) { CVector3 lightVectorTemp = light->position - point; double distanceLight = lightVectorTemp.Length(); double distanceLight2 = distanceLight * distanceLight; lightVectorTemp.Normalize(); double lightShadow = AuxShadow(input2, distanceLight, lightVectorTemp); double intensity = light->intensity * 100.0; newColour.R += lightShadow * light->colour.R / 65536.0 / distanceLight2 * intensity; newColour.G += lightShadow * light->colour.G / 65536.0 / distanceLight2 * intensity; newColour.B += lightShadow * light->colour.B / 65536.0 / distanceLight2 * intensity; } } } if (params->ambientOcclusionEnabled && params->ambientOcclusionMode == params::AOmodeMultipeRays) { sRGBAfloat AO = AmbientOcclusion(input2); newColour.R += AO.R * params->ambientOcclusion; newColour.G += AO.G * params->ambientOcclusion; newColour.B += AO.B * params->ambientOcclusion; } if (opacity > 1.0) opacity = 1.0; output.R = output.R * (1.0 - opacity) + newColour.R * opacity * fogColR / 65536.0; output.G = output.G * (1.0 - opacity) + newColour.G * opacity * fogColG / 65536.0; output.B = output.B * (1.0 - opacity) + newColour.B * opacity * fogColB / 65536.0; totalOpacity = opacity + (1.0 - opacity) * totalOpacity; output.A = opacity + (1.0 - opacity) * output.A; } } if (totalOpacity > 1.0) totalOpacity = 1.0; if (output.A > 1.0) output.A = 1.0; (*opacityOut).R = totalOpacity; (*opacityOut).G = totalOpacity; (*opacityOut).B = totalOpacity; } // next stepCount return output; }
void FilterLinearKeysTemplate( TArray<T>& Keys, TArray<float>& Times, TArray<FTransform>& BoneAtoms, const TArray<float>* ParentTimes, const TArray<FTransform>& RawWorldBones, const TArray<FTransform>& NewWorldBones, const TArray<int32>& TargetBoneIndices, int32 NumFrames, int32 BoneIndex, int32 ParentBoneIndex, float ParentScale, float MaxDelta, float MaxTargetDelta, float EffectorDiffSocket, const TArray<FBoneData>& BoneData ) { const int32 KeyCount = Keys.Num(); check( Keys.Num() == Times.Num() ); check( KeyCount >= 1 ); // generate new arrays we will fill with the final keys TArray<T> NewKeys; TArray<float> NewTimes; NewKeys.Empty(KeyCount); NewTimes.Empty(KeyCount); // Only bother doing anything if we have some keys! if(KeyCount > 0) { int32 LowKey = 0; int32 HighKey = KeyCount-1; int32 PrevKey = 0; // copy the low key (this one is a given) NewTimes.Add(Times[0]); NewKeys.Add(Keys[0]); FTransform DummyBone(FQuat::Identity, FVector(END_EFFECTOR_SOCKET_DUMMY_BONE_SIZE, END_EFFECTOR_SOCKET_DUMMY_BONE_SIZE, END_EFFECTOR_SOCKET_DUMMY_BONE_SIZE)); float const DeltaThreshold = (BoneData[BoneIndex].IsEndEffector() && (BoneData[BoneIndex].bHasSocket || BoneData[BoneIndex].bKeyEndEffector)) ? EffectorDiffSocket : MaxTargetDelta; // We will test within a sliding window between LowKey and HighKey. // Therefore, we are done when the LowKey exceeds the range while (LowKey < KeyCount-1) { // high key always starts at the top of the range HighKey = KeyCount-1; // keep testing until the window is closed while (HighKey > LowKey+1) { // get the parameters of the window we are testing const float LowTime = Times[LowKey]; const float HighTime = Times[HighKey]; const T LowValue = Keys[LowKey]; const T HighValue = Keys[HighKey]; const float Range = HighTime - LowTime; const float InvRange = 1.0f/Range; // iterate through all interpolated members of the window to // compute the error when compared to the original raw values float MaxLerpError = 0.0f; float MaxTargetError = 0.0f; for (int32 TestKey = LowKey+1; TestKey< HighKey; ++TestKey) { // get the parameters of the member being tested float TestTime = Times[TestKey]; T TestValue = Keys[TestKey]; // compute the proposed, interpolated value for the key const float Alpha = (TestTime - LowTime) * InvRange; const T LerpValue = Interpolate(LowValue, HighValue, Alpha); // compute the error between our interpolated value and the desired value float LerpError = CalcDelta(TestValue, LerpValue); // if the local-space lerp error is within our tolerances, we will also check the // effect this interpolated key will have on our target end effectors float TargetError = -1.0f; if (LerpError <= MaxDelta) { // get the raw world transform for this bone (the original world-space position) const int32 FrameIndex = TestKey; const FTransform& RawBase = RawWorldBones[(BoneIndex*NumFrames) + FrameIndex]; // generate the proposed local bone atom and transform (local space) FTransform ProposedTM = UpdateBoneAtom(BoneIndex, BoneAtoms[FrameIndex], LerpValue); // convert the proposed local transform to world space using this bone's parent transform const FTransform& CurrentParent = ParentBoneIndex != INDEX_NONE ? NewWorldBones[(ParentBoneIndex*NumFrames) + FrameIndex] : FTransform::Identity; FTransform ProposedBase = ProposedTM * CurrentParent; // for each target end effector, compute the error we would introduce with our proposed key for (int32 TargetIndex=0; TargetIndex<TargetBoneIndices.Num(); ++TargetIndex) { // find the offset transform from the raw base to the end effector const int32 TargetBoneIndex = TargetBoneIndices[TargetIndex]; FTransform RawTarget = RawWorldBones[(TargetBoneIndex*NumFrames) + FrameIndex]; const FTransform& RelTM = RawTarget.GetRelativeTransform(RawBase); // forecast where the new end effector would be using our proposed key FTransform ProposedTarget = RelTM * ProposedBase; // If this is an EndEffector with a Socket attached to it, add an extra bone, to measure error introduced by effector rotation compression. if( BoneData[TargetIndex].bHasSocket || BoneData[TargetIndex].bKeyEndEffector ) { ProposedTarget = DummyBone * ProposedTarget; RawTarget = DummyBone * RawTarget; } // determine the extend of error at the target end effector float ThisError = (ProposedTarget.GetTranslation() - RawTarget.GetTranslation()).Size(); TargetError = FMath::Max(TargetError, ThisError); // exit early when we encounter a large delta float const TargetDeltaThreshold = BoneData[TargetIndex].bHasSocket ? EffectorDiffSocket : DeltaThreshold; if( TargetError > TargetDeltaThreshold ) { break; } } } // If the parent has a key at this time, we'll scale our error values as requested. // This increases the odds that we will choose keys on the same frames as our parent bone, // making the skeleton more uniform in key distribution. if (ParentTimes) { if (ParentTimes->Find(TestTime) != INDEX_NONE) { // our parent has a key at this time, // inflate our perceived error to increase our sensitivity // for also retaining a key at this time LerpError *= ParentScale; TargetError *= ParentScale; } } // keep track of the worst errors encountered for both // the local-space 'lerp' error and the end effector drift we will cause MaxLerpError = FMath::Max(MaxLerpError, LerpError); MaxTargetError = FMath::Max(MaxTargetError, TargetError); // exit early if we have failed in this span if (MaxLerpError > MaxDelta || MaxTargetError > DeltaThreshold) { break; } } // determine if the span succeeded. That is, the worst errors found are within tolerances if (MaxLerpError <= MaxDelta && MaxTargetError <= DeltaThreshold) { // save the high end of the test span as our next key NewTimes.Add(Times[HighKey]); NewKeys.Add(Keys[HighKey]); // start testing a new span LowKey = HighKey; HighKey = KeyCount-1; } else { // we failed, shrink the test span window and repeat --HighKey; } } // if the test window is still valid, accept the high key if (HighKey > LowKey) { NewTimes.Add(Times[HighKey]); NewKeys.Add(Keys[HighKey]); } LowKey= HighKey; } // The process has ended, but we must make sure the last key is accounted for if (NewTimes.Last() != Times.Last() && CalcDelta(Keys.Last(), NewKeys.Last()) >= MaxDelta ) { NewTimes.Add(Times.Last()); NewKeys.Add(Keys.Last()); } // return the new key set to the caller Times= NewTimes; Keys= NewKeys; } }
void expand_macro_one(StringA& str) { if( str.IsBlockNull() ) return ; //loop do { //find uintptr uCount = 0; uintptr uStart = 0; do { auto iter(StringHelper::Find(str, '{', uStart)); if( iter.IsNull() ) break; intptr delta = iter.CalcDelta(str.GetAt(uStart)); if( iter != str.GetBegin() ) { auto iter1(iter); iter1.MovePrev(); // \{ if( iter1.get_Value() == '\\' ) { uStart += (delta + 1); continue; } } uStart += (delta + 1); uCount ++; uintptr uLeftC = uStart; do { auto iterE(StringHelper::Find(str, '}', uStart)); if( iterE.IsNull() ) { uCount --; break; } delta = iterE.CalcDelta(str.GetAt(uStart)); auto iter1(iterE); iter1.MovePrev(); // \} if( iter1.get_Value() == '\\' ) { uStart += (delta + 1); continue; } uStart += (delta + 1); intptr len = iterE.CalcDelta(iter); //empty if( len <= 1 ) { uCount --; break; } //macro name StringA strMacro(StringHelper::MakeEmptyString<CharA>(MemoryHelper::GetCrtMemoryManager())); //may throw StringUtilHelper::Sub(str, uLeftC, len - 1, strMacro); //may throw ConstStringA c_macro_name(StringUtilHelper::To_ConstString(strMacro)); StringA strV; uint id = m_macro_table.get_ID(c_macro_name); if( id == 0 ) { id = m_token_table.get_ID(c_macro_name); if( id == 0 ) { uCount --; break; } strV = m_token_regex[id - m_token_table.GetMinID()].get_Value(); } else { strV = m_macro_regex[id - m_macro_table.GetMinID()].get_Value(); } iter.get_Value() = '('; iterE.get_Value() = ')'; StringHelper::Delete(uLeftC, len - 1, str); StringUtilHelper::Insert(uLeftC, strV, str); //may throw //now iterators are invalid uStart = uLeftC + strV.GetLength() + 1; break; } while(true); } while(true); if( uCount == 0 ) break; } while(true); }
cRenderWorker::sRayRecursionOut cRenderWorker::RayRecursion(sRayRecursionIn in, sRayRecursionInOut &inOut) { sRayMarchingOut rayMarchingOut; *inOut.rayMarchingInOut.buffCount = 0; //trace the light in given direction CVector3 point = RayMarching(in.rayMarchingIn, &inOut.rayMarchingInOut, &rayMarchingOut); sRGBAfloat resultShader = in.resultShader; sRGBAfloat objectColour = in.objectColour; //here will be called branch for RayRecursion(); sRGBAfloat objectShader; objectShader.A = 0.0; sRGBAfloat backgroundShader; sRGBAfloat volumetricShader; sRGBAfloat specular; //prepare data for shaders CVector3 lightVector = shadowVector; sShaderInputData shaderInputData; shaderInputData.distThresh = rayMarchingOut.distThresh; shaderInputData.delta = CalcDelta(point); shaderInputData.lightVect = lightVector; shaderInputData.point = point; shaderInputData.viewVector = in.rayMarchingIn.direction; shaderInputData.lastDist = rayMarchingOut.lastDist; shaderInputData.depth = rayMarchingOut.depth; shaderInputData.stepCount = *inOut.rayMarchingInOut.buffCount; shaderInputData.stepBuff = inOut.rayMarchingInOut.stepBuff; shaderInputData.invertMode = in.calcInside; shaderInputData.objectId = rayMarchingOut.objectId; cObjectData objectData = data->objectData[shaderInputData.objectId]; shaderInputData.material = &data->materials[objectData.materialId]; sRGBAfloat reflectShader = in.resultShader; double reflect = shaderInputData.material->reflectance; sRGBAfloat transparentShader = in.resultShader; double transparent = shaderInputData.material->transparencyOfSurface; sRGBfloat transparentColor = sRGBfloat(shaderInputData.material->transparencyInteriorColor.R / 65536.0, shaderInputData.material->transparencyInteriorColor.G / 65536.0, shaderInputData.material->transparencyInteriorColor.B / 65536.0); resultShader.R = transparentColor.R; resultShader.G = transparentColor.G; resultShader.B = transparentColor.B; CVector3 vn; //if found any object if (rayMarchingOut.found) { //calculate normal vector vn = CalculateNormals(shaderInputData); shaderInputData.normal = vn; if(shaderInputData.material->diffusionTexture.IsLoaded()) shaderInputData.texDiffuse = TextureShader(shaderInputData, cMaterial::texDiffuse, shaderInputData.material); else shaderInputData.texDiffuse = sRGBfloat(1.0, 1.0, 1.0); if(shaderInputData.material->normalMapTexture.IsLoaded()) { vn = NormalMapShader(shaderInputData); } //prepare refraction values double n1, n2; if (in.calcInside) //if trance is inside the object { n1 = shaderInputData.material ->transparencyIndexOfRefraction; //reverse refractive indices n2 = 1.0; } else { n1 = 1.0; n2 = shaderInputData.material ->transparencyIndexOfRefraction; ; } if (inOut.rayIndex < reflectionsMax) { //calculate refraction (transparency) if (transparent > 0.0) { sRayRecursionIn recursionIn; sRayMarchingIn rayMarchingIn; sRayMarchingInOut rayMarchingInOut; //calculate direction of refracted light CVector3 newDirection = RefractVector(vn, in.rayMarchingIn.direction, n1, n2); //move starting point a little CVector3 newPoint = point + in.rayMarchingIn.direction * shaderInputData.distThresh * 1.0; //if is total internal reflection the use reflection instead of refraction bool internalReflection = false; if (newDirection.Length() == 0.0) { newDirection = ReflectionVector(vn, in.rayMarchingIn.direction); newPoint = point + in.rayMarchingIn.direction * shaderInputData.distThresh * 1.0; internalReflection = true; } //preparation for new recursion rayMarchingIn.binaryEnable = true; rayMarchingIn.direction = newDirection; rayMarchingIn.maxScan = params->viewDistanceMax; rayMarchingIn.minScan = 0.0; rayMarchingIn.start = newPoint; rayMarchingIn.invertMode = !in.calcInside || internalReflection; recursionIn.rayMarchingIn = rayMarchingIn; recursionIn.calcInside = !in.calcInside || internalReflection; recursionIn.resultShader = resultShader; recursionIn.objectColour = objectColour; //setup buffers for ray data inOut.rayIndex++; //increase recursion index rayMarchingInOut.buffCount = &rayBuffer[inOut.rayIndex].buffCount; rayMarchingInOut.stepBuff = rayBuffer[inOut.rayIndex].stepBuff; inOut.rayMarchingInOut = rayMarchingInOut; //recursion for refraction sRayRecursionOut recursionOutTransparent = RayRecursion(recursionIn, inOut); transparentShader = recursionOutTransparent.resultShader; } //calculate reflection if (reflect > 0.0) { sRayRecursionIn recursionIn; sRayMarchingIn rayMarchingIn; sRayMarchingInOut rayMarchingInOut; //calculate new direction of reflection CVector3 newDirection = ReflectionVector(vn, in.rayMarchingIn.direction); CVector3 newPoint = point + newDirection * shaderInputData.distThresh; //prepare for new recursion rayMarchingIn.binaryEnable = true; rayMarchingIn.direction = newDirection; rayMarchingIn.maxScan = params->viewDistanceMax; rayMarchingIn.minScan = 0.0; rayMarchingIn.start = newPoint; rayMarchingIn.invertMode = false; recursionIn.rayMarchingIn = rayMarchingIn; recursionIn.calcInside = false; recursionIn.resultShader = resultShader; recursionIn.objectColour = objectColour; //setup buffers for ray data inOut.rayIndex++; //increase recursion index rayMarchingInOut.buffCount = &rayBuffer[inOut.rayIndex].buffCount; rayMarchingInOut.stepBuff = rayBuffer[inOut.rayIndex].stepBuff; inOut.rayMarchingInOut = rayMarchingInOut; //recursion for reflection sRayRecursionOut recursionOutReflect = RayRecursion(recursionIn, inOut); reflectShader = recursionOutReflect.resultShader; } if (transparent > 0.0) inOut.rayIndex--; //decrease recursion index if (reflect > 0.0) inOut.rayIndex--; //decrease recursion index } shaderInputData.normal = vn; //calculate effects for object surface objectShader = ObjectShader(shaderInputData, &objectColour, &specular); //calculate reflectance according to Fresnel equations double reflectance = 1.0; double reflectanceN = 1.0; if (shaderInputData.material->fresnelReflectance) { reflectance = Reflectance(vn, in.rayMarchingIn.direction, n1, n2); if (reflectance < 0.0) reflectance = 0.0; if (reflectance > 1.0) reflectance = 1.0; reflectanceN = 1.0 - reflectance; } //combine all results resultShader.R = (objectShader.R + specular.R); resultShader.G = (objectShader.G + specular.G); resultShader.B = (objectShader.B + specular.B); if (reflectionsMax > 0) { sRGBfloat reflectDiffused; double diffIntes = shaderInputData.material->diffussionTextureIntensity; double diffIntesN = 1.0 - diffIntes; reflectDiffused.R = reflect * shaderInputData.texDiffuse.R * diffIntes + reflect * diffIntesN; reflectDiffused.G = reflect * shaderInputData.texDiffuse.G * diffIntes + reflect * diffIntesN; reflectDiffused.B = reflect * shaderInputData.texDiffuse.B * diffIntes + reflect * diffIntesN; resultShader.R = transparentShader.R * transparent * reflectanceN + (1.0 - transparent * reflectanceN) * resultShader.R; resultShader.G = transparentShader.G * transparent * reflectanceN + (1.0 - transparent * reflectanceN) * resultShader.G; resultShader.B = transparentShader.B * transparent * reflectanceN + (1.0 - transparent * reflectanceN) * resultShader.B; resultShader.R = reflectShader.R * reflectDiffused.R * reflectance + (1.0 - reflectDiffused.R * reflectance) * resultShader.R; resultShader.G = reflectShader.G * reflectDiffused.G * reflectance + (1.0 - reflectDiffused.G * reflectance) * resultShader.G; resultShader.B = reflectShader.B * reflectDiffused.B * reflectance + (1.0 - reflectDiffused.B * reflectance) * resultShader.B; } if(resultShader.R < 0.0) resultShader.R = 0.0; if(resultShader.G < 0.0) resultShader.G = 0.0; if(resultShader.B < 0.0) resultShader.B = 0.0; } else //if object not found then calculate background { backgroundShader = BackgroundShader(shaderInputData); resultShader = backgroundShader; shaderInputData.depth = 1e20; vn = mRot.RotateVector(CVector3(0.0, -1.0, 0.0)); } sRGBAfloat opacityOut; if (in.calcInside) //if the object interior is traced, then the absorption of light has to be calculated { for (int index = shaderInputData.stepCount - 1; index > 0; index--) { double step = shaderInputData.stepBuff[index].step; //CVector3 point = shaderInputData.stepBuff[index].point; //shaderInputData.point = point; //sRGBAfloat color = SurfaceColour(shaderInputData); //transparentColor.R = color.R; //transparentColor.G = color.G; //transparentColor.B = color.B; double opacity = -log(shaderInputData.material ->transparencyOfInterior) * step; if (opacity > 1.0) opacity = 1.0; resultShader.R = opacity * transparentColor.R + (1.0 - opacity) * resultShader.R; resultShader.G = opacity * transparentColor.G + (1.0 - opacity) * resultShader.G; resultShader.B = opacity * transparentColor.B + (1.0 - opacity) * resultShader.B; } } else //if now is outside the object, then calculate all volumetric effects like fog, glow... { volumetricShader = VolumetricShader(shaderInputData, resultShader, &opacityOut); resultShader = volumetricShader; } //prepare final result sRayRecursionOut out; out.point = point; out.rayMarchingOut = rayMarchingOut; out.objectColour = objectColour; out.resultShader = resultShader; out.found = (shaderInputData.depth == 1e20) ? false : true; out.fogOpacity = opacityOut.R; out.normal = vn; return out; }