// Copied from irrlicht void calculateTangents( core::vector3df& normal, core::vector3df& tangent, core::vector3df& binormal, const core::vector3df& vt1, const core::vector3df& vt2, const core::vector3df& vt3, // vertices const core::vector2df& tc1, const core::vector2df& tc2, const core::vector2df& tc3) // texture coords { core::vector3df v1 = vt1 - vt2; core::vector3df v2 = vt3 - vt1; normal = v2.crossProduct(v1); normal.normalize(); // binormal f32 deltaX1 = tc1.X - tc2.X; f32 deltaX2 = tc3.X - tc1.X; binormal = (v1 * deltaX2) - (v2 * deltaX1); binormal.normalize(); // tangent f32 deltaY1 = tc1.Y - tc2.Y; f32 deltaY2 = tc3.Y - tc1.Y; tangent = (v1 * deltaY2) - (v2 * deltaY1); tangent.normalize(); // adjust core::vector3df txb = tangent.crossProduct(binormal); if (txb.dotProduct(normal) < 0.0f) { tangent *= -1.0f; binormal *= -1.0f; } }
//██████████████████████████████████████████████████████████████████████████████████ // reflection with normal core::vector3df getReflected( core::vector3df vector, core::vector3df normal ) { f32 length = (f32)vector.getLength(); vector.normalize(); normal.normalize(); return (vector - normal * 2.0f * (vector.dotProduct( normal))) * length; }
void ShaderOnSetConstants(IShader *shader) override { shader->SetPixelConstant("rippleScroll", engine->GetRenderUpdater().GetVirtualTime() * 0.02); // Are we looking in to the sun? core::vector3df camVec = maths::rotation_to_direction( engine->GetWorld()->GetCamera()->GetRotation() ); sunDirection.normalize(); f32 dp = camVec.dotProduct(sunDirection); //f32 brightness = 1.f + 0.5 * dp*dp*dp*dp*dp*dp*dp*dp*dp*dp*dp*dp*dp*dp*dp*dp; f32 brightness = 1.f + 0.5 * dp*dp*dp*dp*dp*dp*dp*dp*dp*dp; if (brightness < 1.f || camVec.getDistanceFrom(sunDirection) > 1.f) brightness = 1.f; brightness = core::lerp(lastBrightness, brightness, core::clamp(engine->GetRenderUpdater().GetLastDeltaTime(), 0.f, 1.f)); lastBrightness = brightness; shader->SetPixelConstant("brightness", brightness); }
int main() { srand((u32)time(0)); // This is to generate random seeds. IrrlichtDevice* device = createDevice(video::EDT_OPENGL); CEventReceiver receiver; device->setEventReceiver(&receiver); manager = device->getSceneManager(); driver = device->getVideoDriver(); gui::IGUIEnvironment* guienv = device->getGUIEnvironment(); // // Load tree designs // for (s32 i = 0; i<NUM_TREE_DESIGNS; i++) { treeDesigns[i].Generator = new CTreeGenerator(manager); io::IXMLReader* xml = device->getFileSystem()->createXMLReader(treeDesignFiles[i].DesignFile); treeDesigns[i].Generator->loadFromXML(xml); xml->drop(); treeDesigns[i].TreeTexture = driver->getTexture(treeDesignFiles[i].TreeTextureFile); treeDesigns[i].LeafTexture = driver->getTexture(treeDesignFiles[i].LeafTextureFile); treeDesigns[i].BillTexture = driver->getTexture(treeDesignFiles[i].BillTextureFile); } // // Load leaf shader // leafMaterialType = (video::E_MATERIAL_TYPE) driver->getGPUProgrammingServices()->addHighLevelShaderMaterialFromFiles( "./shaders/leaves.vert", "main", EVST_VS_2_0, "./shaders/leaves.frag", "main", EPST_PS_2_0, 0, EMT_TRANSPARENT_ALPHA_CHANNEL, 0); // // Tree scene node // tree = new CTreeSceneNode(manager->getRootSceneNode(), manager); tree->drop(); tree->setMaterialFlag(video::EMF_LIGHTING, lightsEnabled); // // Camera // scene::ICameraSceneNode* camera = manager->addCameraSceneNodeFPS(0, 100, 100); camera->setPosition(core::vector3df(23.4f, 233.4f, -150.9f)); // // Light // scene::ILightSceneNode* light = manager->addLightSceneNode(0, core::vector3df(100, 100, 100), video::SColorf(1, 1, 1, 1), 10000.0f); light->getLightData().AmbientColor.set(0.25f, 0.25f, 0.25f, 0.25f); lightDir = core::vector3df(-1, -1, -1); lightDir.normalize(); generateNewTree(); // // Interface // guienv->getSkin()->setColor(gui::EGDC_BUTTON_TEXT, video::SColor(255, 200, 255, 255)); guienv->addStaticText(L"By Asger Feldthaus", core::rect<s32>(10, 40, 100, 60)); guienv->addStaticText(L"F6: Toggle lighting", core::rect<s32>(10, 260, 100, 280)); guienv->addStaticText(L"F7: Previous tree design", core::rect<s32>(10, 280, 100, 300)); guienv->addStaticText(L"F8: Next tree design", core::rect<s32>(10, 300, 100, 320)); guienv->addStaticText(L"F9: Generate new tree", core::rect<s32>(10, 320, 100, 340)); // // Run loop // while (device->run()) { // // Render // driver->beginScene(true, true, video::SColor(0, 40, 40, 40)); manager->drawAll(); guienv->drawAll(); driver->endScene(); // // Window caption // wchar_t caption[60]; s32 tri = driver->getPrimitiveCountDrawn(); swprintf(&caption[0], 60, L"FPS: %i, Triangles: %i, Vertices: %i", driver->getFPS(), tri, tree->getVertexCount()); device->setWindowCaption(&caption[0]); // // Controls // if (receiver.TappedKeys[KEY_F6]) { lightsEnabled = !lightsEnabled; tree->setMaterialFlag(video::EMF_LIGHTING, lightsEnabled); if (lightsEnabled) tree->getLeafNode()->applyVertexShadows(lightDir, 1.0f, 0.25f); else tree->getLeafNode()->resetVertexShadows(); } if (receiver.TappedKeys[KEY_F7]) { currentTreeDesign--; if (currentTreeDesign < 0) currentTreeDesign += NUM_TREE_DESIGNS; generateNewTree(); } if (receiver.TappedKeys[KEY_F8]) { currentTreeDesign = (currentTreeDesign + 1) % NUM_TREE_DESIGNS; generateNewTree(); } if (receiver.TappedKeys[KEY_F9]) { seed = rand(); generateNewTree(); } if (receiver.TappedKeys[KEY_ESCAPE]) { device->closeDevice(); } receiver.reset(); } // // Clean up // for (s32 i = 0; i<NUM_TREE_DESIGNS; i++) { treeDesigns[i].Generator->drop(); } device->drop(); return 0; }