void shader( GLWindow& window, GLRenderer& renderer ) { auto camera = PerspectiveCamera::create( 60, ( float )renderer.width() / renderer.height(), 1, 10000 ); camera->position().z = 300; auto scene = Scene::create(); auto texture = ImageUtils::loadTexture( threeDataPath( "textures/sprites/spark1.png" ) ); Uniforms uniforms; uniforms[ "color" ] = Uniform( THREE::c, Color( 0xffffff ) ); uniforms[ "texture" ] = Uniform( THREE::t, texture.get() ); Attributes attributes; attributes[ "size" ] = Attribute( THREE::f ); attributes[ "customColor" ] = Attribute( THREE::c ); auto shaderMaterial = ShaderMaterial::create( vertexShader, fragmentShader, uniforms, attributes, Material::Parameters().add( "blending", THREE::AdditiveBlending ) .add( "depthTest", false ) .add( "transparent", true ) ); // Geometries const auto radius = 200.f; const auto pointCount = 100000; auto geometry = Geometry::create(); auto& vertices = geometry->vertices; vertices.reserve( pointCount ); std::generate_n( std::back_inserter(vertices), pointCount, [=]() -> Vector3 { return Vector3( Math::random(-1.f, 1.f), Math::random(-1.f, 1.f), Math::random(-1.f, 1.f) ).multiplyScalar( radius ); } ); auto sphere = ParticleSystem::create( geometry, shaderMaterial ); sphere->geometry->dynamic = true; sphere->sortParticles = false; std::vector<float> values_size( pointCount ); std::vector<Color> values_color( pointCount ); for ( int v = 0; v < pointCount; v++ ) { values_size[ v ] = 10; values_color[ v ].set( 0xffaa00 ); if ( vertices[ v ].x < 0 ) values_color[ v ].setHSL( 0.5f + 0.1f * ( (float)v / pointCount ), 0.7f, 0.5f ); else values_color[ v ].setHSL( 0.0f + 0.1f * ( (float)v / pointCount), 0.9f, 0.5f ); } auto& size = shaderMaterial->attributes[ "size" ]; auto& color = shaderMaterial->attributes[ "customColor" ]; size.value = values_size; color.value = values_color; scene->add( sphere ); ///////////////////////////////////////////////////////////////////////// window.addEventListener( SDL_WINDOWEVENT, [&]( const SDL_Event& event ) { if (event.window.event != SDL_WINDOWEVENT_RESIZED) return; camera->aspect = ( float )event.window.data1 / event.window.data2; camera->updateProjectionMatrix(); renderer.setSize( event.window.data1, event.window.data2 ); } ); ///////////////////////////////////////////////////////////////////////// auto time = 0.f; window.animate( [&]( float dt ) -> bool { time += dt; sphere->rotation().z = time * 0.03f; auto& sizes = size.value.cast<std::vector<float>>(); for( size_t i = 0; i < sizes.size(); i++ ) { sizes[ i ] = 10.f + 9.f * Math::sin( 0.1f * i + time * 3.f ); } size.needsUpdate = true; renderer.render( *scene, *camera ); return true; } ); }
void geometries( GLWindow& window, GLRenderer& renderer ) { auto camera = PerspectiveCamera::create( 45, ( float )renderer.width() / renderer.height(), 10, 20000 ); camera->position().y = 700; auto scene = Scene::create(); scene->add( AmbientLight::create( 0x404040 ) ); auto light = DirectionalLight::create( 0xffffff ); light->position().set( 0, 1, 0 ); scene->add( light ); auto map = ImageUtils::loadTexture( threeDataPath( "textures/UV_Grid_Sm.jpg" ) ); map->wrapS = map->wrapT = THREE::RepeatWrapping; map->anisotropy = 16; auto material = MeshLambertMaterial::create( Material::Parameters() .add( "ambient", Color( 0xbbbbbb ) ) .add( "map", map ) .add( "side", THREE::DoubleSide ) ); // auto sphere = Mesh::create( SphereGeometry::create( 75, 20, 10 ), material ); sphere->position().set( -400, 0, 200 ); scene->add( sphere ); auto ico = Mesh::create( IcosahedronGeometry::create( 75, 1 ), material ); ico->position().set( -200, 0, 200 ); scene->add( ico ); auto octa = Mesh::create( OctahedronGeometry::create( 75, 2 ), material ); octa->position().set( 0, 0, 200 ); scene->add( octa ); auto tetra = Mesh::create( TetrahedronGeometry::create( 75, 0 ), material ); tetra->position().set( 200, 0, 200 ); scene->add( tetra ); // auto plane = Mesh::create( PlaneGeometry::create( 100, 100, 4, 4 ), material ); plane->position().set( -400, 0, 0 ); scene->add( plane ); auto cube = Mesh::create( BoxGeometry::create( 100, 100, 100, 4, 4, 4 ), material ); cube->position().set( -200, 0, 0 ); scene->add( cube ); auto circle = Mesh::create( CircleGeometry::create( 50, 20, 0, Math::PI() * 2 ), material ); circle->position().set( 0, 0, 0 ); scene->add( circle ); auto ring = Mesh::create( RingGeometry::create( 10, 50, 20, 5, 0, Math::PI() * 2 ), material ); ring->position().set( 200, 0, 0 ); scene->add( ring ); auto cylinder = Mesh::create( CylinderGeometry::create( 25, 75, 100, 40, 5 ), material ); cylinder->position().set( 400, 0, 0 ); scene->add( cylinder ); // std::vector<Vector3> points; for ( auto i = 0; i < 50; i ++ ) { points.push_back( Vector3( Math::sin( (float)i * 0.2 ) * Math::sin( (float)i * 0.1 ) * 15 + 50, 0, ( (float)i - 5 ) * 2 ) ); } auto lathe = Mesh::create( LatheGeometry::create( points, 20 ), material ); lathe->position().set( -400, 0, -200 ); scene->add( lathe ); auto torus = Mesh::create( TorusGeometry::create( 50, 20, 20, 20 ), material ); torus->position().set( -200, 0, -200 ); scene->add( torus ); auto torusKnot = Mesh::create( TorusKnotGeometry::create( 50, 10, 50, 20 ), material ); torusKnot->position().set( 0, 0, -200 ); scene->add( torusKnot ); auto axis = AxisHelper::create( 50 ); axis->position().set( 200, 0, -200 ); scene->add( axis ); auto arrow = ArrowHelper::create( Vector3( 0, 1, 0 ), Vector3( 0, 0, 0 ) ); arrow->setLength(50); arrow->position().set( 400, 0, -200 ); scene->add( arrow ); ///////////////////////////////////////////////////////////////////////// window.addEventListener( SDL_WINDOWEVENT, [&]( const SDL_Event& event ) { if (event.window.event != SDL_WINDOWEVENT_RESIZED) return; camera->aspect = ( float )event.window.data1 / event.window.data2; camera->updateProjectionMatrix(); renderer.setSize( event.window.data1, event.window.data2 ); } ); ///////////////////////////////////////////////////////////////////////// auto time = 0.f; int benchmarkFrames = 100000; window.animate( [&]( float dt ) -> bool { time += dt; camera->position().x = Math::cos( time * 0.2 ) * 800; camera->position().z = Math::sin( time * 0.2 ) * 800; camera->lookAt( scene->position() ); for ( size_t i = 0; i < scene->children.size(); i ++ ) { auto& object = scene->children[ i ]; object->rotation().x = time * 1; object->rotation().y = time * 0.25; } renderer.render( *scene, *camera ); return --benchmarkFrames > 0; } ); }
void particles_billboards( GLWindow& window, GLRenderer& renderer ) { auto camera = PerspectiveCamera::create( 55, ( float )renderer.width() / renderer.height(), 2.f, 2000 ); camera->position().z = 1000; auto scene = Scene::create(); scene->fog = FogExp2::create( 0x000000, .001f ); auto geometry = Geometry::create(); const auto particleCount = 10000; geometry->vertices.reserve( particleCount ); std::generate_n( std::back_inserter( geometry->vertices ), particleCount, [] { return Vector3( Math::random(-1000.f, 1000.f), Math::random(-1000.f, 1000.f), Math::random(-1000.f, 1000.f) ); } ); auto sprite = ImageUtils::loadTexture( threeDataPath("textures/sprites/disc.png") ); auto material = ParticleSystemMaterial::create( Material::Parameters().add( "size", 35.f ) .add( "map", sprite ) .add( "sizeAttenuation", false ) .add( "transparent", true) ); material->color.setHSL( 1.f, 0.3f, 0.7f ); auto particles = ParticleSystem::create( geometry, material ); particles->sortParticles = true; scene->add( particles ); ///////////////////////////////////////////////////////////////////////// auto mouseX = 0.f, mouseY = 0.f; window.addEventListener( SDL_MOUSEMOTION, [&]( const SDL_Event& event ) { mouseX = 2.f * ( ( float )event.motion.x / renderer.width() - 0.5f ); mouseY = 2.f * ( ( float )event.motion.y / renderer.height() - 0.5f ); } ); window.addEventListener( SDL_WINDOWEVENT, [&]( const SDL_Event& event ) { if (event.window.event != SDL_WINDOWEVENT_RESIZED) return; camera->aspect = ( float )event.window.data1 / event.window.data2; camera->updateProjectionMatrix(); renderer.setSize( event.window.data1, event.window.data2 ); } ); ///////////////////////////////////////////////////////////////////////// auto time = 0.f; window.animate( [&]( float dt ) -> bool { time += dt * .05f; camera->position().x += ( -1000.f * mouseX - camera->position().x ) * 3 * dt; camera->position().y += ( 1000.f * mouseY - camera->position().y ) * 3 * dt; camera->lookAt( scene->position() ); const auto h = Math::fmod( 360.f * ( 1.f + time ), 360.f ) / 360.f; material->color.setHSL( h, 0.5f, 0.5f ); renderer.render( *scene, *camera ); return true; } ); }
void particles_sprites( GLWindow& window, GLRenderer& renderer ) { auto camera = PerspectiveCamera::create( 75, ( float )renderer.width() / renderer.height(), 1.f, 2000 ); camera->position().z = 1000; auto scene = Scene::create(); scene->fog = FogExp2::create( 0x000000, .0008f ); auto geometry = Geometry::create(); auto sprite1 = ImageUtils::loadTexture( threeDataPath("textures/sprites/snowflake1.png") ); auto sprite2 = ImageUtils::loadTexture( threeDataPath("textures/sprites/snowflake2.png") ); auto sprite3 = ImageUtils::loadTexture( threeDataPath("textures/sprites/snowflake3.png") ); auto sprite4 = ImageUtils::loadTexture( threeDataPath("textures/sprites/snowflake4.png") ); auto sprite5 = ImageUtils::loadTexture( threeDataPath("textures/sprites/snowflake5.png") ); const auto particleCount = 10000; geometry->vertices.reserve( particleCount ); std::generate_n( std::back_inserter( geometry->vertices ), particleCount, [] { return Vector3( Math::random(-1000.f, 1000.f), Math::random(-1000.f, 1000.f), Math::random(-1000.f, 1000.f) ); } ); std::vector<Material::Ptr> materials; auto addParticleSystem = [&]( const Vector3& color, const Texture::Ptr& sprite, float size ) { auto material = ParticleSystemMaterial::create( Material::Parameters().add( "size", size ) .add( "map", sprite ) .add( "blending", THREE::AdditiveBlending ) .add( "depthTest", false ) .add( "transparent", true ) ); materials.push_back( material ); material->color.setHSL( color[0], color[1], color[2] ); auto particles = ParticleSystem::create( geometry, material ); particles->rotation() = Euler( Math::random() * 6, Math::random() * 6, Math::random() * 6 ); scene->add( particles ); }; typedef std::tuple<Vector3, Texture::Ptr, float> ColorSpriteSize; std::array<ColorSpriteSize, 5> params = { ColorSpriteSize( Vector3( 1.f, 0.2f, 0.5f), sprite2, 20.f ), ColorSpriteSize( Vector3(0.95f, 0.1f, 0.5f), sprite3, 13.f ), ColorSpriteSize( Vector3(0.90f, 0.05f, 0.5f), sprite1, 10.f ), ColorSpriteSize( Vector3(0.85f, 0.f, 0.5f), sprite5, 8.f ), ColorSpriteSize( Vector3(0.80f, 0.f, 0.5f), sprite4, 5.f ) }; for ( const auto& param : params ) { addParticleSystem( std::get<0>(param), std::get<1>(param), std::get<2>(param) ); } ///////////////////////////////////////////////////////////////////////// auto mouseX = 0.f, mouseY = 0.f; window.addEventListener( SDL_MOUSEMOTION, [&]( const SDL_Event& event ) { mouseX = 2.f * ( ( float )event.motion.x / renderer.width() - 0.5f ); mouseY = 2.f * ( ( float )event.motion.y / renderer.height() - 0.5f ); } ); window.addEventListener( SDL_WINDOWEVENT, [&]( const SDL_Event& event ) { if (event.window.event != SDL_WINDOWEVENT_RESIZED) return; camera->aspect = ( float )event.window.data1 / event.window.data2; camera->updateProjectionMatrix(); renderer.setSize( event.window.data1, event.window.data2 ); } ); ///////////////////////////////////////////////////////////////////////// auto time = 0.f; window.animate( [&]( float dt ) -> bool { time += dt * .05f; camera->position().x += ( -1000.f * mouseX - camera->position().x ) * 3 * dt; camera->position().y += ( 1000.f * mouseY - camera->position().y ) * 3 * dt; camera->lookAt( scene->position() ); for ( size_t i = 0; i < scene->children.size(); ++i ) { auto& object = *scene->children[ i ]; if ( object.type() == THREE::ParticleSystem ) { object.rotation().y = time * ( i < 4 ? i + 1 : - ( (int)i + 1 ) ); } } for ( size_t i = 0; i < materials.size(); ++i ) { auto& color = std::get<0>(params[ i ]); const auto h = Math::fmod( 360.f * ( color[0] + time ), 360.f ) / 360.f; materials[ i ]->color.setHSL( h, color[ 1 ], color[ 2 ] ); } renderer.render( *scene, *camera ); return true; } ); }