diff --git a/interface/src/Stars.cpp b/interface/src/Stars.cpp index 3ef909786d..02c4ffd32f 100644 --- a/interface/src/Stars.cpp +++ b/interface/src/Stars.cpp @@ -24,6 +24,10 @@ #include #include +#include "../../libraries/render-utils/standardTransformPNTC_vert.h" +#include "../../libraries/render-utils/stars_frag.h" + +static const float TILT = 0.23f; static const unsigned int STARFIELD_NUM_STARS = 50000; static const unsigned int STARFIELD_SEED = 1; static const float STAR_COLORIZATION = 0.1f; @@ -34,14 +38,9 @@ static const float QUARTER_TAU = TAU / 4.0f; static const float MILKY_WAY_WIDTH = TAU / 30.0f; // width in radians of one half of the Milky Way static const float MILKY_WAY_INCLINATION = 0.0f; // angle of Milky Way from horizontal in degrees static const float MILKY_WAY_RATIO = 0.4f; +static const char* UNIFORM_TIME_NAME = "iGlobalTime"; -#include "../../libraries/render-utils/standardTransformPNTC_vert.h" -const char stars_frag[] = R"SCRIBE(#version 430 compatibility -void main(void) { - gl_FragColor = vec4( 1.0 ); -} -)SCRIBE"; Stars::Stars() { } @@ -112,16 +111,16 @@ void Stars::render(RenderArgs* renderArgs, float alpha) { static gpu::BufferPointer vertexBuffer; static gpu::Stream::FormatPointer streamFormat; static gpu::Element positionElement, colorElement; + static gpu::PipelinePointer _pipeline; + static int32_t _timeSlot{ -1 }; + static std::once_flag once; const int VERTICES_SLOT = 0; const int COLOR_SLOT = 2; - static std::once_flag once; - std::call_once(once, [&] { QElapsedTimer startTime; startTime.start(); - vertexBuffer.reset(new gpu::Buffer); srand(STARFIELD_SEED); @@ -139,18 +138,45 @@ void Stars::render(RenderArgs* renderArgs, float alpha) { positionElement = streamFormat->getAttributes().at(gpu::Stream::POSITION)._element; double timeDiff = (double)startTime.nsecsElapsed() / 1000000.0; // ns to ms qDebug() << "Total time to generate stars: " << timeDiff << " msec"; + + auto vs = gpu::ShaderPointer(gpu::Shader::createVertex(std::string(standardTransformPNTC_vert))); + auto ps = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(stars_frag))); + auto program = gpu::ShaderPointer(gpu::Shader::createProgram(vs, ps)); + gpu::Shader::makeProgram((*program)); + _timeSlot = program->getBuffers().findLocation(UNIFORM_TIME_NAME); + if (_timeSlot == gpu::Shader::INVALID_LOCATION) { + _timeSlot = program->getUniforms().findLocation(UNIFORM_TIME_NAME); + } + auto state = gpu::StatePointer(new gpu::State()); + // enable decal blend + state->setDepthTest(gpu::State::DepthTest(false)); + state->setBlendFunction(true, gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA); + _pipeline.reset(gpu::Pipeline::create(program, state)); }); - gpu::Batch batch; - batch.setInputFormat(streamFormat); - batch.setInputBuffer(VERTICES_SLOT, gpu::BufferView(vertexBuffer, positionElement)); - batch.setViewTransform(Transform()); - batch.setProjectionTransform(renderArgs->_viewFrustum->getProjection()); - batch.setModelTransform(Transform().setRotation(glm::inverse(renderArgs->_viewFrustum->getOrientation()))); auto geometryCache = DependencyManager::get(); auto textureCache = DependencyManager::get(); - geometryCache->useSimpleDrawPipeline(batch); + + gpu::Batch batch; + batch.setViewTransform(Transform()); + batch.setProjectionTransform(renderArgs->_viewFrustum->getProjection()); + batch.setModelTransform(Transform().setRotation(glm::inverse(renderArgs->_viewFrustum->getOrientation()) * + quat(vec3(TILT, 0, 0)))); batch.setResourceTexture(0, textureCache->getWhiteTexture()); + + // Render the world lines + batch.setPipeline(_pipeline); + static auto start = usecTimestampNow(); + float msecs = (float)(usecTimestampNow() - start) / (float)USECS_PER_MSEC; + float secs = msecs / (float)MSECS_PER_SECOND; + batch._glUniform1f(_timeSlot, secs); + geometryCache->renderUnitCube(batch); + + + // Render the stars + geometryCache->useSimpleDrawPipeline(batch); + batch.setInputFormat(streamFormat); + batch.setInputBuffer(VERTICES_SLOT, gpu::BufferView(vertexBuffer, positionElement)); batch.draw(gpu::Primitive::POINTS, STARFIELD_NUM_STARS); renderArgs->_context->render(batch); } diff --git a/libraries/render-utils/src/stars.slf b/libraries/render-utils/src/stars.slf index f0f81cb5f4..344d196230 100644 --- a/libraries/render-utils/src/stars.slf +++ b/libraries/render-utils/src/stars.slf @@ -1,5 +1,6 @@ <@include gpu/Config.slh@> <$VERSION_HEADER$> +#line __LINE__ // Generated on <$_SCRIBE_DATE$> // stars.frag // fragment shader @@ -10,67 +11,53 @@ varying vec2 varTexcoord; varying vec3 varNomral; varying vec3 varPosition; +uniform float iGlobalTime; -const int star_iterations = 14; -const float time_scale = 0.2; -const vec3 col_star = vec3( 1.0, 0.7, 0.5 ); +const float PI = 3.14159; +const float TAU = 3.14159 * 2.0; +const int latitudeCount = 5; +const float latitudeDist = PI / 2.0 / float(latitudeCount); +const int meridianCount = 4; +const float merdianDist = PI / float(meridianCount); -float hash( float n ) { return fract(sin(n)*123.456789); } -vec2 rotate( in vec2 uv, float a) -{ - float c = cos( a ); - float s = sin( a ); - return vec2( c * uv.x - s * uv.y, s * uv.x + c * uv.y ); +float clampLine(float val, float target) { + return clamp((1.0 - abs((val - target)) - 0.998) * 500.0, 0.0, 1.0); } -float noise( in vec3 p ) -{ - vec3 fl = floor( p ); - vec3 fr = fract( p ); - fr = fr * fr * ( 3.0 - 2.0 * fr ); - - float n = fl.x + fl.y * 157.0 + 113.0 * fl.z; - return mix( mix( mix( hash( n + 0.0), hash( n + 1.0 ), fr.x ), - mix( hash( n + 157.0), hash( n + 158.0 ), fr.x ), fr.y ), - mix( mix( hash( n + 113.0), hash( n + 114.0 ), fr.x ), - mix( hash( n + 270.0), hash( n + 271.0 ), fr.x ), fr.y ), fr.z ); -} - -float fbm( in vec2 p, float t ) -{ - float f; - f = 0.5000 * noise( vec3( p, t ) ); p *= 2.1; - f += 0.2500 * noise( vec3( p, t ) ); p *= 2.2; - f += 0.1250 * noise( vec3( p, t ) ); p *= 2.3; - f += 0.0625 * noise( vec3( p, t ) ); - return f; -} - -vec3 doBackgroundStars( in vec3 dir ) -{ - vec3 n = abs( dir ); - vec2 uv = ( n.x > n.y && n.x > n.z ) ? dir.yz / dir.x: - ( n.y > n.x && n.y > n.z ) ? dir.zx / dir.y: - dir.xy / dir.z; - - float f = 0.0; - - for( int i = 0 ; i < star_iterations; ++i ) - { - uv = rotate( 1.07 * uv + vec2( 0.7 ), 0.5 ); - - float t = 10. * uv.x * uv.y; - vec2 u = cos( 100. * uv ) * fbm( 10. * uv, 0.0 ); - f += smoothstep( 0.5, 0.55, u.x * u.y ) * ( 0.25 * sin( t ) + 0.75 ); +float latitude(vec2 pos, float angle) { + float result = clampLine(pos.y, angle); + if (angle != 0.0) { + result += clampLine(pos.y, -angle); } - - return f * col_star; + return result; +} + +float meridian(vec2 pos, float angle) { + return clampLine(pos.x, angle) + clampLine(pos.x + PI, angle); +} + +vec2 toPolar(in vec3 dir) { + vec2 polar = vec2(atan(dir.z, dir.x), asin(dir.y)); + return polar; +} + +void mainVR( out vec4 fragColor, in vec2 fragCoord, in vec3 fragRayOri, in vec3 fragRayDir ) +{ + vec2 polar = toPolar(fragRayDir); + polar.x += mod(iGlobalTime / 12.0, PI / 4.0) - PI / 4.0; + float c = 0.0; + for (int i = 0; i < latitudeCount - 1; ++i) { + c += latitude(polar, float(i) * latitudeDist); + } + for (int i = 0; i < meridianCount; ++i) { + c += meridian(polar, float(i) * merdianDist); + } + const vec3 col_lines = vec3(102.0 / 255.0, 136.0 / 255.0, 221.0 / 255.0); + fragColor = vec4(c * col_lines, 1.0); } void main(void) { - vec3 c = doBackgroundStars( normalize(varPosition) ); - c = pow( c, vec3( 0.4545 ) ); - gl_FragColor = vec4( c, 1.0 ); + mainVR(gl_FragColor, gl_FragCoord.xy, vec3(0.0), normalize(varPosition)); }