增加大气渲染范例
This commit is contained in:
parent
90826198a7
commit
8461f31b1a
160
example/Vulkan/Atomsphere.cpp
Normal file
160
example/Vulkan/Atomsphere.cpp
Normal file
@ -0,0 +1,160 @@
|
|||||||
|
// 8.大气渲染
|
||||||
|
// 画一个球,纯粹使用shader计算出颜色
|
||||||
|
|
||||||
|
#include"VulkanAppFramework.h"
|
||||||
|
#include<hgl/filesystem/FileSystem.h>
|
||||||
|
#include<hgl/graph/InlineGeometry.h>
|
||||||
|
#include<hgl/graph/SceneDB.h>
|
||||||
|
#include<hgl/graph/RenderableInstance.h>
|
||||||
|
#include<hgl/graph/RenderList.h>
|
||||||
|
|
||||||
|
using namespace hgl;
|
||||||
|
using namespace hgl::graph;
|
||||||
|
|
||||||
|
constexpr uint32_t SCREEN_WIDTH=128;
|
||||||
|
constexpr uint32_t SCREEN_HEIGHT=128;
|
||||||
|
|
||||||
|
struct AtomsphereData
|
||||||
|
{
|
||||||
|
alignas(16) Vector3f position;
|
||||||
|
float intensity;
|
||||||
|
float scattering_direction;
|
||||||
|
};//
|
||||||
|
|
||||||
|
class TestApp:public CameraAppFramework
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
SceneNode render_root;
|
||||||
|
RenderList render_list;
|
||||||
|
|
||||||
|
vulkan::Material * material =nullptr;
|
||||||
|
vulkan::DescriptorSets * descriptor_sets =nullptr;
|
||||||
|
|
||||||
|
vulkan::Renderable *ro_sphere;
|
||||||
|
|
||||||
|
vulkan::Pipeline *pipeline_solid =nullptr;
|
||||||
|
|
||||||
|
vulkan::Buffer * ubo_atomsphere =nullptr;
|
||||||
|
AtomsphereData atomsphere_data;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
bool InitMaterial()
|
||||||
|
{
|
||||||
|
material=shader_manage->CreateMaterial(OS_TEXT("Atomsphere.vert.spv"),
|
||||||
|
OS_TEXT("Atomsphere.frag.spv"));
|
||||||
|
if(!material)
|
||||||
|
return(false);
|
||||||
|
|
||||||
|
descriptor_sets=material->CreateDescriptorSets();
|
||||||
|
|
||||||
|
db->Add(material);
|
||||||
|
db->Add(descriptor_sets);
|
||||||
|
return(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CreateRenderObject()
|
||||||
|
{
|
||||||
|
ro_sphere=CreateRenderableSphere(db,material,16);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool InitAtomsphereUBO(vulkan::DescriptorSets *desc_set,uint bindpoint)
|
||||||
|
{
|
||||||
|
atomsphere_data.position.Set(0,0.1f,-1.0f);
|
||||||
|
atomsphere_data.intensity=22.0f;
|
||||||
|
atomsphere_data.scattering_direction=0.758f;
|
||||||
|
|
||||||
|
ubo_atomsphere=db->CreateUBO(sizeof(AtomsphereData),&atomsphere_data);
|
||||||
|
|
||||||
|
if(!ubo_atomsphere)
|
||||||
|
return(false);
|
||||||
|
|
||||||
|
return desc_set->BindUBO(bindpoint,*ubo_atomsphere);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool InitUBO()
|
||||||
|
{
|
||||||
|
if(!InitCameraUBO(descriptor_sets,material->GetUBO("world")))
|
||||||
|
return(false);
|
||||||
|
|
||||||
|
if(!InitAtomsphereUBO(descriptor_sets,material->GetUBO("sun")))
|
||||||
|
return(false);
|
||||||
|
|
||||||
|
descriptor_sets->Update();
|
||||||
|
return(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool InitPipeline()
|
||||||
|
{
|
||||||
|
vulkan::PipelineCreater *pipeline_creater=new vulkan::PipelineCreater(device,material,device->GetRenderPass(),device->GetExtent());
|
||||||
|
pipeline_creater->SetDepthTest(true);
|
||||||
|
pipeline_creater->SetDepthWrite(true);
|
||||||
|
pipeline_creater->SetCullMode(VK_CULL_MODE_NONE);
|
||||||
|
pipeline_creater->Set(PRIM_TRIANGLES);
|
||||||
|
pipeline_solid=pipeline_creater->Create();
|
||||||
|
|
||||||
|
if(!pipeline_solid)
|
||||||
|
return(false);
|
||||||
|
|
||||||
|
db->Add(pipeline_solid);
|
||||||
|
|
||||||
|
delete pipeline_creater;
|
||||||
|
return(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool InitScene()
|
||||||
|
{
|
||||||
|
render_root.Add(db->CreateRenderableInstance(pipeline_solid,descriptor_sets,ro_sphere),scale(1000));
|
||||||
|
|
||||||
|
render_root.RefreshMatrix();
|
||||||
|
render_root.ExpendToList(&render_list);
|
||||||
|
|
||||||
|
return(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
bool Init()
|
||||||
|
{
|
||||||
|
if(!CameraAppFramework::Init(SCREEN_WIDTH,SCREEN_HEIGHT))
|
||||||
|
return(false);
|
||||||
|
|
||||||
|
if(!InitMaterial())
|
||||||
|
return(false);
|
||||||
|
|
||||||
|
CreateRenderObject();
|
||||||
|
|
||||||
|
if(!InitUBO())
|
||||||
|
return(false);
|
||||||
|
|
||||||
|
if(!InitPipeline())
|
||||||
|
return(false);
|
||||||
|
|
||||||
|
if(!InitScene())
|
||||||
|
return(false);
|
||||||
|
|
||||||
|
return(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BuildCommandBuffer(uint32_t index) override
|
||||||
|
{
|
||||||
|
render_root.RefreshMatrix();
|
||||||
|
render_list.Clear();
|
||||||
|
render_root.ExpendToList(&render_list);
|
||||||
|
|
||||||
|
VulkanApplicationFramework::BuildCommandBuffer(index,&render_list);
|
||||||
|
}
|
||||||
|
};//class TestApp:public CameraAppFramework
|
||||||
|
|
||||||
|
int main(int,char **)
|
||||||
|
{
|
||||||
|
TestApp app;
|
||||||
|
|
||||||
|
if(!app.Init())
|
||||||
|
return(-1);
|
||||||
|
|
||||||
|
while(app.Run());
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
@ -15,4 +15,6 @@ target_link_libraries(6.LoadModel assimp)
|
|||||||
|
|
||||||
CreateProject(7.InlineGeometryScene InlineGeometryScene.cpp)
|
CreateProject(7.InlineGeometryScene InlineGeometryScene.cpp)
|
||||||
|
|
||||||
CreateProject(8.RenderToColor RenderToColor.cpp TGATexture.cpp)
|
CreateProject(8.Atomsphere Atomsphere.cpp)
|
||||||
|
|
||||||
|
CreateProject(9.RenderToColor RenderToColor.cpp TGATexture.cpp)
|
141
res/shader/Atomsphere.frag
Normal file
141
res/shader/Atomsphere.frag
Normal file
@ -0,0 +1,141 @@
|
|||||||
|
#version 450 core
|
||||||
|
|
||||||
|
#define PI 3.141592
|
||||||
|
#define iSteps 16
|
||||||
|
#define jSteps 8
|
||||||
|
|
||||||
|
layout(location = 0) in vec4 FragmentVertex;
|
||||||
|
|
||||||
|
layout(location = 0) out vec4 FragColor;
|
||||||
|
|
||||||
|
layout(binding = 1) uniform AtomSphere
|
||||||
|
{
|
||||||
|
vec3 position;
|
||||||
|
float intensity;
|
||||||
|
float scattering_direction;
|
||||||
|
}sun;
|
||||||
|
|
||||||
|
vec2 rsi(vec3 r0, vec3 rd, float sr) {
|
||||||
|
// ray-sphere intersection that assumes
|
||||||
|
// the sphere is centered at the origin.
|
||||||
|
// No intersection when result.x > result.y
|
||||||
|
float a = dot(rd, rd);
|
||||||
|
float b = 2.0 * dot(rd, r0);
|
||||||
|
float c = dot(r0, r0) - (sr * sr);
|
||||||
|
float d = (b*b) - 4.0*a*c;
|
||||||
|
if (d < 0.0) return vec2(1e5,-1e5);
|
||||||
|
return vec2(
|
||||||
|
(-b - sqrt(d))/(2.0*a),
|
||||||
|
(-b + sqrt(d))/(2.0*a)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 atmosphere(vec3 r, vec3 r0, vec3 pSun, float iSun, float rPlanet, float rAtmos, vec3 kRlh, float kMie, float shRlh, float shMie, float g)
|
||||||
|
{
|
||||||
|
// Normalize the sun and view directions.
|
||||||
|
pSun = normalize(pSun);
|
||||||
|
r = normalize(r);
|
||||||
|
|
||||||
|
// Calculate the step size of the primary ray.
|
||||||
|
vec2 p = rsi(r0, r, rAtmos);
|
||||||
|
if (p.x > p.y) return vec3(0,0,0);
|
||||||
|
p.y = min(p.y, rsi(r0, r, rPlanet).x);
|
||||||
|
float iStepSize = (p.y - p.x) / float(iSteps);
|
||||||
|
|
||||||
|
// Initialize the primary ray time.
|
||||||
|
float iTime = 0.0;
|
||||||
|
|
||||||
|
// Initialize accumulators for Rayleigh and Mie scattering.
|
||||||
|
vec3 totalRlh = vec3(0,0,0);
|
||||||
|
vec3 totalMie = vec3(0,0,0);
|
||||||
|
|
||||||
|
// Initialize optical depth accumulators for the primary ray.
|
||||||
|
float iOdRlh = 0.0;
|
||||||
|
float iOdMie = 0.0;
|
||||||
|
|
||||||
|
// Calculate the Rayleigh and Mie phases.
|
||||||
|
float mu = dot(r, pSun);
|
||||||
|
float mumu = mu * mu;
|
||||||
|
float gg = g * g;
|
||||||
|
float pRlh = 3.0 / (16.0 * PI) * (1.0 + mumu);
|
||||||
|
float pMie = 3.0 / (8.0 * PI) * ((1.0 - gg) * (mumu + 1.0)) / (pow(1.0 + gg - 2.0 * mu * g, 1.5) * (2.0 + gg));
|
||||||
|
|
||||||
|
// Sample the primary ray.
|
||||||
|
for (int i = 0; i < iSteps; i++) {
|
||||||
|
|
||||||
|
// Calculate the primary ray sample position.
|
||||||
|
vec3 iPos = r0 + r * (iTime + iStepSize * 0.5);
|
||||||
|
|
||||||
|
// Calculate the height of the sample.
|
||||||
|
float iHeight = length(iPos) - rPlanet;
|
||||||
|
|
||||||
|
// Calculate the optical depth of the Rayleigh and Mie scattering for this step.
|
||||||
|
float odStepRlh = exp(-iHeight / shRlh) * iStepSize;
|
||||||
|
float odStepMie = exp(-iHeight / shMie) * iStepSize;
|
||||||
|
|
||||||
|
// Accumulate optical depth.
|
||||||
|
iOdRlh += odStepRlh;
|
||||||
|
iOdMie += odStepMie;
|
||||||
|
|
||||||
|
// Calculate the step size of the secondary ray.
|
||||||
|
float jStepSize = rsi(iPos, pSun, rAtmos).y / float(jSteps);
|
||||||
|
|
||||||
|
// Initialize the secondary ray time.
|
||||||
|
float jTime = 0.0;
|
||||||
|
|
||||||
|
// Initialize optical depth accumulators for the secondary ray.
|
||||||
|
float jOdRlh = 0.0;
|
||||||
|
float jOdMie = 0.0;
|
||||||
|
|
||||||
|
// Sample the secondary ray.
|
||||||
|
for (int j = 0; j < jSteps; j++) {
|
||||||
|
|
||||||
|
// Calculate the secondary ray sample position.
|
||||||
|
vec3 jPos = iPos + pSun * (jTime + jStepSize * 0.5);
|
||||||
|
|
||||||
|
// Calculate the height of the sample.
|
||||||
|
float jHeight = length(jPos) - rPlanet;
|
||||||
|
|
||||||
|
// Accumulate the optical depth.
|
||||||
|
jOdRlh += exp(-jHeight / shRlh) * jStepSize;
|
||||||
|
jOdMie += exp(-jHeight / shMie) * jStepSize;
|
||||||
|
|
||||||
|
// Increment the secondary ray time.
|
||||||
|
jTime += jStepSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate attenuation.
|
||||||
|
vec3 attn = exp(-(kMie * (iOdMie + jOdMie) + kRlh * (iOdRlh + jOdRlh)));
|
||||||
|
|
||||||
|
// Accumulate scattering.
|
||||||
|
totalRlh += odStepRlh * attn;
|
||||||
|
totalMie += odStepMie * attn;
|
||||||
|
|
||||||
|
// Increment the primary ray time.
|
||||||
|
iTime += iStepSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate and return the final color.
|
||||||
|
return iSun * (pRlh * kRlh * totalRlh + pMie * kMie * totalMie);
|
||||||
|
}
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
vec3 nrd=vec3(.x,-FragmentVertex.y,FragmentVertex.z); //vulkan coord to opengl(shader from opengl sample)
|
||||||
|
|
||||||
|
vec3 color=atmosphere(
|
||||||
|
nrd, // normalized ray direction
|
||||||
|
vec3(0,6372e3,0), // ray origin
|
||||||
|
sun.position, // position of the sun
|
||||||
|
sun.intensity, // intensity of the sun
|
||||||
|
6371e3, // radius of the planet in meters
|
||||||
|
6471e3, // radius of the atmosphere in meters
|
||||||
|
vec3(5.5e-6, 13.0e-6, 22.4e-6), // Rayleigh scattering coefficient
|
||||||
|
21e-6, // Mie scattering coefficient
|
||||||
|
8e3, // Rayleigh scale height
|
||||||
|
1.2e3, // Mie scale height
|
||||||
|
sun.scattering_direction // Mie preferred scattering direction
|
||||||
|
);
|
||||||
|
|
||||||
|
FragColor=vec4(1.0-exp(-color),1);
|
||||||
|
}
|
24
res/shader/Atomsphere.vert
Normal file
24
res/shader/Atomsphere.vert
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
#version 450 core
|
||||||
|
|
||||||
|
layout(location = 0) in vec3 Vertex;
|
||||||
|
|
||||||
|
layout(binding = 0) uniform WorldMatrix
|
||||||
|
{
|
||||||
|
mat4 two_dim;
|
||||||
|
mat4 projection;
|
||||||
|
mat4 modelview;
|
||||||
|
mat4 mvp;
|
||||||
|
mat3 normal;
|
||||||
|
} world;
|
||||||
|
|
||||||
|
layout(push_constant) uniform Consts {
|
||||||
|
mat4 local_to_world;
|
||||||
|
} pc;
|
||||||
|
|
||||||
|
layout(location = 0) out vec4 FragmentVertex;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
FragmentVertex=vec4(Vertex,1.0)*pc.local_to_world*world.mvp;
|
||||||
|
gl_Position=FragmentVertex;
|
||||||
|
}
|
@ -11,3 +11,6 @@ glslangValidator -V -o OnlyPosition3D.vert.spv OnlyPosition3D.vert
|
|||||||
|
|
||||||
glslangValidator -V -o c_gbuffer.vert.spv c_gbuffer.vert
|
glslangValidator -V -o c_gbuffer.vert.spv c_gbuffer.vert
|
||||||
glslangValidator -V -o c_gbuffer.frag.spv c_gbuffer.frag
|
glslangValidator -V -o c_gbuffer.frag.spv c_gbuffer.frag
|
||||||
|
|
||||||
|
glslangValidator -V -o Atomsphere.vert.spv Atomsphere.vert
|
||||||
|
glslangValidator -V -o Atomsphere.frag.spv Atomsphere.frag
|
||||||
|
Loading…
x
Reference in New Issue
Block a user