Last active
March 1, 2022 23:23
-
-
Save ofTheo/3dadcd7c442da7f27e3e0af1cf70d9c8 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "ofApp.h" | |
#include "SampleUtils.h" | |
#include "utils/ComboRenderPipelineDescriptor.h" | |
#include "utils/DawnHelpers.h" | |
#include "utils/SystemUtils.h" | |
#include "GLFW/glfw3.h" | |
//Our stuff | |
int windowW = 1024; | |
int windowH = 800; | |
vector <float> vertDataConvOF; | |
vector <uint32_t> indexDataOF; | |
ofMesh mesh; | |
int meshMode = 1; | |
//Dawn stuff | |
dawn::Device device; | |
dawn::Buffer indexBuffer; | |
dawn::Buffer vertexBuffer; | |
dawn::Buffer cameraBuffer; | |
dawn::Buffer transformBuffer[2]; | |
dawn::BindGroup cameraBindGroup; | |
dawn::BindGroup bindGroup[4]; | |
dawn::Texture texture; | |
dawn::Sampler sampler; | |
dawn::Queue dawnQueue; | |
dawn::SwapChain swapchain; | |
dawn::TextureView depthStencilView; | |
dawn::RenderPipeline pipeline; | |
dawn::RenderPipeline planePipeline; | |
dawn::RenderPipeline reflectionPipeline; | |
struct CameraData { | |
glm::mat4 view; | |
glm::mat4 proj; | |
} cameraData; | |
//mostly pulled from CppHelloTriangle.cpp example - void initTextures() | |
//note the code in this seems to have changed a lot in the last few months - so a more up to date Dawn might need some language changes in here | |
void makeTextureFromOFPixels( ofPixels & pix ) { | |
dawn::TextureDescriptor descriptor; | |
descriptor.dimension = dawn::TextureDimension::e2D; | |
descriptor.size.width = pix.getWidth(); | |
descriptor.size.height = pix.getHeight(); | |
descriptor.size.depth = 1; | |
descriptor.arrayLayerCount = 1; | |
descriptor.sampleCount = 1; | |
if( pix.getNumChannels() == 4 ){ | |
descriptor.format = dawn::TextureFormat::RGBA8Unorm; | |
}else{ | |
descriptor.format = dawn::TextureFormat::RGBA8Unorm; | |
pix.setNumChannels(4); | |
ofLogWarning("Dawn needs 4 channels"); | |
} | |
descriptor.mipLevelCount = 1; | |
descriptor.usage = dawn::TextureUsageBit::CopyDst | dawn::TextureUsageBit::Sampled; | |
texture = device.CreateTexture(&descriptor); | |
dawn::SamplerDescriptor samplerDesc = utils::GetDefaultSamplerDescriptor(); | |
sampler = device.CreateSampler(&samplerDesc); | |
dawn::Buffer stagingBuffer = utils::CreateBufferFromData(device, pix.getData(), static_cast<uint32_t>(pix.size()), dawn::BufferUsageBit::CopySrc); | |
dawn::BufferCopyView bufferCopyView = utils::CreateBufferCopyView(stagingBuffer, 0, 0, 0); | |
dawn::TextureCopyView textureCopyView = utils::CreateTextureCopyView(texture, 0, 0, {0, 0, 0}); | |
dawn::Extent3D copySize = { (uint32_t)pix.getWidth(), (uint32_t)pix.getHeight(), 1}; | |
dawn::CommandEncoder encoder = device.CreateCommandEncoder(); | |
encoder.CopyBufferToTexture(&bufferCopyView, &textureCopyView, ©Size); | |
dawn::CommandBuffer copy = encoder.Finish(); | |
dawnQueue.Submit(1, ©); | |
} | |
void makeBufferFromOfMesh( ofMesh & mesh ){ | |
//set the index data for the mesh from ofMesh | |
indexDataOF.clear(); | |
for(auto & index : mesh.getIndices() ){ | |
indexDataOF.push_back( index ); | |
} | |
size_t sizeIndexes = sizeof(uint32_t) * indexDataOF.size(); | |
indexBuffer = utils::CreateBufferFromData(device, &indexDataOF[0], sizeIndexes, dawn::BufferUsageBit::Index); | |
//now we make a float vector with all our per-vertex data | |
//pos, color, normal, texture etc - adds up to 11 floats | |
vertDataConvOF.resize( mesh.getVertices().size() * 11 ); | |
glm::vec3 c = glm::vec3(1, 1, 1); | |
glm::vec3 n = glm::vec3(0, 1, 0); | |
glm::vec2 t = glm::vec2(1, 1); | |
auto colors = mesh.getColors(); | |
auto normals = mesh.getNormals(); | |
auto texCoords = mesh.getTexCoords(); | |
int i = 0; | |
int k = 0; | |
for(auto & v : mesh.getVertices()){ | |
if( k < colors.size() ){ | |
c.r = colors[k].r; | |
c.g = colors[k].g; | |
c.b = colors[k].b; | |
} | |
if( k < normals.size() ){ | |
n = normals[k]; | |
} | |
if( k < texCoords.size() ){ | |
t = texCoords[k]; | |
} | |
//position data | |
vertDataConvOF[i] = v.x; | |
vertDataConvOF[i+1] = v.y; | |
vertDataConvOF[i+2] = v.z; | |
//color data | |
vertDataConvOF[i+3] = c.r; | |
vertDataConvOF[i+4] = c.g; | |
vertDataConvOF[i+5] = c.b; | |
//normal data | |
vertDataConvOF[i+6] = n.x; | |
vertDataConvOF[i+7] = n.y; | |
vertDataConvOF[i+8] = n.z; | |
//texcoord data | |
vertDataConvOF[i+9] = t.x; | |
vertDataConvOF[i+10] = 1.0-t.y; | |
k++; | |
i+= 11; | |
} | |
//now set the per vert data | |
size_t sizeVerts = sizeof(float) * vertDataConvOF.size(); | |
vertexBuffer = utils::CreateBufferFromData(device, &vertDataConvOF[0], sizeVerts, dawn::BufferUsageBit::Vertex); | |
} | |
//doing this here so we don't have to make a window class | |
void keyboard_cb(GLFWwindow* windowP_, int key, int scancode, int action, int mods){ | |
if( key >= '1' && key <= '9' ){ | |
meshMode = key-48; | |
} | |
} | |
//-------------------------------------------------------------- | |
void ofApp::setup(){ | |
//this creates the window - this would be handled in our window class ofAppGLFWDawnWindow or something | |
device = CreateCppDawnDevice(windowW, windowH); | |
//doing this here so we don't have to make a window class | |
glfwSetKeyCallback(GetGLFWWindow(), keyboard_cb); | |
dawnQueue = device.CreateQueue(); | |
swapchain = GetSwapChain(device); | |
swapchain.Configure(GetPreferredSwapChainTextureFormat(), | |
dawn::TextureUsageBit::OutputAttachment, windowW, windowH); | |
//lets load an image :) | |
ofPixels logoPix; | |
ofLoadImage(logoPix, "of-gold.png"); | |
makeTextureFromOFPixels(logoPix); | |
//our vertex shader any in vertex needs to be set in setup() | |
dawn::ShaderModule vsModule = utils::CreateShaderModule(device, dawn::ShaderStage::Vertex, R"( | |
#version 450 | |
layout(set = 0, binding = 0) uniform cameraData { | |
mat4 view; | |
mat4 proj; | |
} camera; | |
layout(set = 0, binding = 1) uniform modelData { | |
mat4 modelMatrix; | |
}; | |
layout(location = 0) in vec3 pos; | |
layout(location = 1) in vec3 col; | |
layout(location = 2) in vec3 nrmal; | |
layout(location = 3) in vec2 texcoord; | |
layout(location = 4) out vec3 f_col; | |
layout(location = 5) out vec2 tcoord_out; | |
void main() { | |
vec3 colMod = col; | |
//fake lighting | |
vec3 camNrml = vec3(0.5, 0.25, 0.2); | |
vec3 vNrmal = (camera.proj * camera.view * modelMatrix * vec4(nrmal, 1.0)).xyz; | |
// | |
float dotVal = dot(normalize(vNrmal), normalize(camNrml)); | |
colMod *= 0.4 + dotVal * 0.5; | |
//copy over the texcoord - feels like we should be able to access this in the frag shader directly | |
tcoord_out = texcoord; | |
f_col = colMod; | |
gl_Position = camera.proj * camera.view * modelMatrix * vec4(pos, 1.0); | |
})" | |
); | |
//fragment shader. binding number is what you set in MakeBindGroupLayout | |
dawn::ShaderModule fsModule = utils::CreateShaderModule(device, dawn::ShaderStage::Fragment, R"( | |
#version 450 | |
layout(set = 0, binding = 2) uniform sampler mySampler; | |
layout(set = 0, binding = 3) uniform texture2D myTexture; | |
layout(location = 0) out vec4 fragColor; | |
layout(location = 4) in vec3 f_col; | |
layout(location = 5) in vec2 tcoord_out; | |
void main() { | |
fragColor = texture(sampler2D(myTexture, mySampler), tcoord_out) * vec4(f_col, 1.0); | |
})"); | |
//our per-vertex data | |
//4 attributes for position, color, normals and tex coords | |
utils::ComboVertexInputDescriptor vertexInput; | |
vertexInput.cBuffers[0].attributeCount = 4; | |
vertexInput.cAttributes[0].format = dawn::VertexFormat::Float3; | |
//for our colors | |
vertexInput.cAttributes[1].shaderLocation = 1; | |
vertexInput.cAttributes[1].offset = 3 * sizeof(float); | |
vertexInput.cAttributes[1].format = dawn::VertexFormat::Float3; | |
//for our normals ( added ) | |
vertexInput.cAttributes[2].shaderLocation = 2; | |
vertexInput.cAttributes[2].offset = 6 * sizeof(float); | |
vertexInput.cAttributes[2].format = dawn::VertexFormat::Float3; | |
//for our tex coords ( added ) | |
vertexInput.cAttributes[3].shaderLocation = 3; | |
vertexInput.cAttributes[3].offset = 9 * sizeof(float); | |
vertexInput.cAttributes[3].format = dawn::VertexFormat::Float2; | |
vertexInput.bufferCount = 1; | |
//size of each vert including pos (3) / color (3) / normal (3) / texcoord (2) | |
vertexInput.cBuffers[0].stride = 11 * sizeof(float); | |
//this is the result of combining two Dawn examples :) | |
//not sure if we need the second Vertex buffer | |
auto bgl = utils::MakeBindGroupLayout( | |
device, { | |
{0, dawn::ShaderStageBit::Vertex, dawn::BindingType::UniformBuffer}, | |
{1, dawn::ShaderStageBit::Vertex, dawn::BindingType::UniformBuffer}, | |
{2, dawn::ShaderStageBit::Fragment, dawn::BindingType::Sampler}, | |
{3, dawn::ShaderStageBit::Fragment, dawn::BindingType::SampledTexture}, | |
}); | |
dawn::PipelineLayout pl = utils::MakeBasicPipelineLayout(device, &bgl); | |
//camera stuff | |
dawn::BufferDescriptor cameraBufDesc; | |
cameraBufDesc.size = sizeof(CameraData); | |
cameraBufDesc.usage = dawn::BufferUsageBit::CopyDst | dawn::BufferUsageBit::Uniform; | |
cameraBuffer = device.CreateBuffer(&cameraBufDesc); | |
glm::mat4 transform(1.0); | |
transformBuffer[0] = utils::CreateBufferFromData(device, &transform, sizeof(glm::mat4), dawn::BufferUsageBit::Uniform); | |
transform = glm::translate(transform, glm::vec3(0.f, -2.f, 0.f)); | |
transformBuffer[1] = utils::CreateBufferFromData(device, &transform, sizeof(glm::mat4), dawn::BufferUsageBit::Uniform); | |
//dont quite understand this all - result of combining two examples | |
dawn::TextureView view = texture.CreateDefaultView(); | |
bindGroup[0] = utils::MakeBindGroup(device, bgl, { | |
{0, cameraBuffer, 0, sizeof(CameraData)}, | |
{1, transformBuffer[0], 0, sizeof(glm::mat4)}, | |
{2, sampler}, | |
{3, view} | |
}); | |
depthStencilView = CreateDefaultDepthStencilView(device, windowW, windowH); | |
utils::ComboRenderPipelineDescriptor descriptor(device); | |
descriptor.layout = pl; | |
descriptor.cVertexStage.module = vsModule; | |
descriptor.cFragmentStage.module = fsModule; | |
descriptor.vertexInput = &vertexInput; | |
descriptor.depthStencilState = &descriptor.cDepthStencilState; | |
descriptor.cDepthStencilState.format = dawn::TextureFormat::Depth24PlusStencil8; | |
descriptor.cColorStates[0]->format = GetPreferredSwapChainTextureFormat(); | |
descriptor.cDepthStencilState.depthWriteEnabled = true; | |
descriptor.cDepthStencilState.depthCompare = dawn::CompareFunction::Less; | |
pipeline = device.CreateRenderPipeline(&descriptor); | |
utils::ComboRenderPipelineDescriptor pDescriptor(device); | |
pDescriptor.layout = pl; | |
pDescriptor.cVertexStage.module = vsModule; | |
pDescriptor.cFragmentStage.module = fsModule; | |
pDescriptor.vertexInput = &vertexInput; | |
pDescriptor.depthStencilState = &pDescriptor.cDepthStencilState; | |
pDescriptor.cDepthStencilState.format = dawn::TextureFormat::Depth24PlusStencil8; | |
pDescriptor.cColorStates[0]->format = GetPreferredSwapChainTextureFormat(); | |
pDescriptor.cDepthStencilState.stencilFront.passOp = dawn::StencilOperation::Replace; | |
pDescriptor.cDepthStencilState.stencilBack.passOp = dawn::StencilOperation::Replace; | |
pDescriptor.cDepthStencilState.depthCompare = dawn::CompareFunction::Less; | |
planePipeline = device.CreateRenderPipeline(&pDescriptor); | |
//camera settings - fov, aspect ratio, near and far | |
cameraData.proj = glm::perspective(glm::radians(45.0f), (float)windowW/((float)windowH), 1.0f, 100.0f); | |
mesh = ofMesh::box(2, 2, 2, 2,2,2); | |
makeBufferFromOfMesh(mesh); | |
} | |
struct {uint32_t a; float b;} s; | |
//-------------------------------------------------------------- | |
void ofApp::update(){ | |
if( ShouldQuit() ){ | |
ofExit(); | |
} | |
s.a = (s.a + 1) % 256; | |
s.b += 0.01f * ofGetLastFrameTime() * 60.0; | |
if (s.b >= 10.0f) {s.b = 0.0f;} | |
//look around | |
cameraData.view = glm::lookAt( | |
glm::vec3(8.f * std::sin(glm::radians(s.b * 4.0f * 36.f)), -2.0f - std::sin(glm::radians(s.b * 0.5 * 360.f)) * 1.2, 8.f * std::cos(glm::radians(s.b * 4.0 * 36.f))), | |
glm::vec3(0.0f, 0.0f, 0.0f), | |
glm::vec3(0.0f, 1.0f, 0.0f) | |
); | |
cameraBuffer.SetSubData(0, sizeof(CameraData), &cameraData); | |
dawn::Texture backbuffer = swapchain.GetNextTexture(); | |
utils::ComboRenderPassDescriptor renderPass({backbuffer.CreateDefaultView()}, | |
depthStencilView); | |
if( meshMode != preMeshMode ){ | |
if( meshMode == 1 ){ | |
mesh = ofMesh::box(2, 2, 2, 2,2,2); | |
}else if( meshMode == 2 ){ | |
mesh = ofMesh::box(0.25, 4, 2, 2,2,2); | |
}else if( meshMode == 3 ){ | |
mesh = ofMesh::cylinder(1, 2, 36, 12, 2, true, OF_PRIMITIVE_TRIANGLES); | |
}else if( meshMode == 4 ){ | |
mesh = ofMesh::cone(1, 2, 36, 12, 2, OF_PRIMITIVE_TRIANGLES); | |
}else if( meshMode == 5 ){ | |
mesh = ofMesh::icosphere(2, 3); | |
}else if( meshMode == 6 ){ | |
auto m = ofPlanePrimitive(4, 4, 4, 4, OF_PRIMITIVE_TRIANGLES); | |
mesh = m.getMesh(); | |
} | |
preMeshMode = meshMode; | |
int numIndexes = mesh.getIndices().size(); | |
makeBufferFromOfMesh(mesh); | |
} | |
dawn::CommandEncoder encoder = device.CreateCommandEncoder(); | |
{ | |
static const uint64_t vertexBufferOffsets[1] = {0}; | |
dawn::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass); | |
pass.SetPipeline(pipeline); | |
pass.SetBindGroup(0, bindGroup[0], 0, nullptr); | |
pass.SetVertexBuffers(0, 1, &vertexBuffer, vertexBufferOffsets); | |
pass.SetIndexBuffer(indexBuffer, 0); | |
pass.DrawIndexed(indexDataOF.size(), 1, 0, 0, 0); | |
pass.EndPass(); | |
} | |
dawn::CommandBuffer commands = encoder.Finish(); | |
dawnQueue.Submit(1, &commands); | |
swapchain.Present(backbuffer); | |
DoFlush(); | |
} | |
//-------------------------------------------------------------- | |
void ofApp::draw(){ | |
} | |
//-------------------------------------------------------------- | |
void ofApp::keyPressed(int key){ | |
} | |
//-------------------------------------------------------------- | |
void ofApp::keyReleased(int key){ | |
} | |
//-------------------------------------------------------------- | |
void ofApp::mouseMoved(int x, int y ){ | |
} | |
//-------------------------------------------------------------- | |
void ofApp::mouseDragged(int x, int y, int button){ | |
} | |
//-------------------------------------------------------------- | |
void ofApp::mousePressed(int x, int y, int button){ | |
} | |
//-------------------------------------------------------------- | |
void ofApp::mouseReleased(int x, int y, int button){ | |
} | |
//-------------------------------------------------------------- | |
void ofApp::mouseEntered(int x, int y){ | |
} | |
//-------------------------------------------------------------- | |
void ofApp::mouseExited(int x, int y){ | |
} | |
//-------------------------------------------------------------- | |
void ofApp::windowResized(int w, int h){ | |
} | |
//-------------------------------------------------------------- | |
void ofApp::gotMessage(ofMessage msg){ | |
} | |
//-------------------------------------------------------------- | |
void ofApp::dragEvent(ofDragInfo dragInfo){ | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment