Vulkan Samples 阅读 -- Hardware Accelerated Ray Tracing(一) Basic Ray Tracing Ray Traced Shadows
目录
- Basic Ray Tracing
- prepare
- render
- shader
- 小结
- Ray Traced Shadows
- prepare
- render
- shader
- 小结
Basic Ray Tracing
prepare
- VkPhysicalDeviceRayTracingPipelinePropertiesKHR
- 获取光追管线属性
- VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PIPELINE_PROPERTIES_KHR
- VkPhysicalDeviceProperties2
- vkGetPhysicalDeviceProperties2
- VkPhysicalDeviceAccelerationStructureFeaturesKHR
- 获取加速属性
- VkPhysicalDeviceFeatures2
- vkGetPhysicalDeviceFeatures2
- 获取此示例所需的与光线跟踪和加速度结构相关的函数指针
- PFN_vkGetBufferDeviceAddressKHR
- PFN_vkCmdBuildAccelerationStructuresKHR
- PFN_vkBuildAccelerationStructuresKHR
- PFN_vkCreateAccelerationStructureKHR
- PFN_vkDestroyAccelerationStructureKHR
- PFN_vkGetAccelerationStructureBuildSizesKHR
- PFN_vkGetAccelerationStructureDeviceAddressKHR
- PFN_vkCmdTraceRaysKHR
- PFN_vkGetRayTracingShaderGroupHandlesKHR
- PFN_vkCreateRayTracingPipelinesKHR
- createBottomLevelAccelerationStructure: 在本地创建模型底层加速结构信息
- 创建包含场景实际几何体(顶点、三角形)的底层加速结构
- 创建一个三角形的VBO IBO
- createBuffer: VBO 这里没有使用staging buffer
- createBuffer: IBO
- createBuffer: Transform buffer
- 创建三个VkDeviceOrHostAddressConstKHR,分别存放三个buffer的指针(deviceAddress)
- vertexBufferDeviceAddress : getBufferDeviceAddress
- indexBufferDeviceAddress: getBufferDeviceAddress
- transformBufferDeviceAddress: getBufferDeviceAddress
- 创建加速结构
- VkAccelerationStructureGeometryKHR
- 参数数模型的一些基本属性
- VkAccelerationStructureBuildGeometryInfoKHR: 几何信息
- VkAccelerationStructureBuildSizesInfoKHR:Get size info
- createAccelerationStructureBuffer: 创建加速结构buffer
- VkBufferCreateInfo:特殊的参数
- sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO
- usage = VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR
- vkCreateBuffer: 下面使用的参数结构体都使用加速结构相关参数
- vkGetBufferMemoryRequirements
- vkAllocateMemory
- vkBindBufferMemory
- VkBufferCreateInfo:特殊的参数
- VkAccelerationStructureCreateInfoKHR
- vkCreateAccelerationStructureKHR: 创建加速结构
- 创建光追加速结构数据buffer
- RayTracingScratchBuffer = createScratchBuffer()
- 创建暂存缓冲区(ScratchBuffer)以保存线追加速结构数据
- RayTracingScratchBuffer:结构体
- VkBufferCreateInfo
- vkCreateBuffer
- vkGetBufferMemoryRequirements
- vkAllocateMemory
- vkBindBufferMemory
- VkBufferDeviceAddressInfoKHR:结构体
- vkGetBufferDeviceAddressKHR
- RayTracingScratchBuffer = createScratchBuffer()
- VkAccelerationStructureBuildGeometryInfoKHR
- VkAccelerationStructureBuildRangeInfoKHR
- accelerationStructureFeatures.accelerationStructureHostCommands
- 获取本机属性, 判断硬件是否支持加速结构创建
- 支持在Host中创建buffer
- vkBuildAccelerationStructuresKHR
- 不支持就在驱动(device)创建
- createCommandBuffer
- vkCmdBuildAccelerationStructuresKHR
- flushCommandBuffer
- VkAccelerationStructureDeviceAddressInfoKHR:结构体
- vkGetAccelerationStructureDeviceAddressKHR
- 获取加速结构指针(address)
- deleteScratchBuffer
- 删除 ScratchBuffer
- vkFreeMemory
- vkDestroyBuffer
- 删除 ScratchBuffer
- VkAccelerationStructureGeometryKHR
- createTopLevelAccelerationStructure: 创建顶层加速结构信息(scene’s object instances)
- TopLevel和BottomLevel的区别, 个人认为 BottomLevel 创建每个面片的AABB的加速结构, 而TopLevel是根据模型AABB创建加速结构
- VkTransformMatrixKHR: 单位矩阵
- VkAccelerationStructureInstanceKHR
- Buffer for instance data
- createBuffer
- VkDeviceOrHostAddressConstKHR
- getBufferDeviceAddress:从用于获取光追所需的缓冲区的设备地址
- VkBufferDeviceAddressInfoKHR
- vkGetBufferDeviceAddressKHR
- VkAccelerationStructureGeometryKHR
- geometryType = VK_GEOMETRY_TYPE_INSTANCES_KHR
- 这里将加速结构的信息设置为instance
- VkAccelerationStructureBuildGeometryInfoKHR:结构体
- VkAccelerationStructureBuildSizesInfoKHR: 结构体
- vkGetAccelerationStructureBuildSizesKHR
- createAccelerationStructureBuffer
- 创建加速结构buffer
- VkAccelerationStructureCreateInfoKHR
- RayTracingScratchBuffer = createScratchBuffer(): BottomLevel 中使用同样方法
- VkAccelerationStructureBuildGeometryInfoKHR
- VkAccelerationStructureBuildRangeInfoKHR
- accelerationStructureFeatures.accelerationStructureHostCommands
- true: vkBuildAccelerationStructuresKHR
- false:
- createCommandBuffer
- vkCmdBuildAccelerationStructuresKHR
- flushCommandBuffer
- VkAccelerationStructureDeviceAddressInfoKHR:结构体
- deleteScratchBuffer
- instancesBuffer.destroy()
- geometryType = VK_GEOMETRY_TYPE_INSTANCES_KHR
- createStorageImage(): 存放光追渲染结果:
- VkImageCreateInfo image = vks::initializers::imageCreateInfo();
- vkCreateImage
- vkGetImageMemoryRequirements
- vkAllocateMemory
- vkBindImageMemory
- VkImageViewCreateInfo
- vkCreateImageView
- createCommandBuffer
- setImageLayout
- flushCommandBuffer - createUniformBuffer
- createBuffer
- updateUniformBuffers
- createRayTracingPipeline
- VkDescriptorSetLayoutBinding:结构体
- VkDescriptorSetLayoutCreateInfo:结构体
- vkCreateDescriptorSetLayout
- VkPipelineLayoutCreateInfo
- vkCreatePipelineLayout
- Setup ray tracing shader groups
- VkPipelineShaderStageCreateInfo
- Ray generation group
- VkRayTracingShaderGroupCreateInfoKHR: 结构体,存放shader和其他配置信息
- shader: raygen.rgen.spv
- VkRayTracingShaderGroupCreateInfoKHR: 结构体,存放shader和其他配置信息
- Miss group: 光追未命中
- VkRayTracingShaderGroupCreateInfoKHR
- shader: miss.rmiss.spv
- Closest hit group: 光追命中
- VkRayTracingShaderGroupCreateInfoKHR
- shader: closesthit.rchit.spv
- Create the ray tracing pipeline
- VkRayTracingPipelineCreateInfoKHR:结构体
- vkCreateRayTracingPipelinesKHR
- createShaderBindingTable
- 创建用于加速结构的 shader 绑定表(Shader Binding Tables)-(SBT)
- vkGetRayTracingShaderGroupHandlesKHR
- createBuffer: 创建SBT – raygen
- 使用字段VK_BUFFER_USAGE_SHADER_BINDING_TABLE_BIT_KHR
- createBuffer: miss
- createBuffer: hit
- memcpy
- memcpy
- memcpy
- createBuffer: 创建SBT – raygen
- createDescriptorSets
- vkCreateDescriptorPool
- vkAllocateDescriptorSets
- writeDescriptorSet
- writeDescriptorSet
- vkUpdateDescriptorSets
- buildCommandBuffers
- handleResize
- vkDestroyImageView
- vkDestroyImage
- vkFreeMemory
- createStorageImage:之前有用到该方法
- vkUpdateDescriptorSets
- vkBeginCommandBuffer
- 在着色器绑定表中设置指向着色器的缓冲区
- VkStridedDeviceAddressRegionKHR: raygen SBT
- getBufferDeviceAddress
- VkStridedDeviceAddressRegionKHR: miss SBT
- getBufferDeviceAddress
- VkStridedDeviceAddressRegionKHR: hit SBT
- getBufferDeviceAddress
- VkStridedDeviceAddressRegionKHR: raygen SBT
- vkCmdBindPipeline
- VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR
- vkCmdBindDescriptorSets
- vkCmdTraceRaysKHR
- Copy ray tracing output to swap chain image
- setImageLayout
- Prepare ray tracing output image as transfer source
- setImageLayout
- vkCmdCopyImage
- setImageLayout
- setImageLayout
- vkEndCommandBuffer
- handleResize
render
- draw
- prepareFrame
- vkQueueSubmit
- submitFrame
- updateUniformBuffers
shader
raygen.rgen:计算与顶层加速结构碰撞的点
- #extension GL_EXT_ray_tracing : enable
//需要绑定topLevel的加速结构 layout(binding = 0, set = 0) uniform accelerationStructureEXT topLevelAS; layout(binding = 1, set = 0, rgba8) uniform image2D image; layout(binding = 2, set = 0) uniform CameraProperties
- layout(location = 0) rayPayloadEXT vec3 hitValue;
- 射线Hit的坐标信息
void main() {//获取像素中心像素值const vec2 pixelCenter = vec2(gl_LaunchIDEXT.xy) + vec2(0.5);//获取获取中心像素对于的uv值const vec2 inUV = pixelCenter/vec2(gl_LaunchSizeEXT.xy);vec2 d = inUV * 2.0 - 1.0;//获取射线的原点,和出射方向vec4 origin = cam.viewInverse * vec4(0,0,0,1);vec4 target = cam.projInverse * vec4(d.x, d.y, 1, 1) ;vec4 direction = cam.viewInverse*vec4(normalize(target.xyz), 0) ;//设置射线t的值范围float tmin = 0.001;float tmax = 10000.0;hitValue = vec3(0.0);//根据topLevel加速结构和射线获取与加速结构碰撞的点坐标//猜测traceRayEXT的结果存储在rayPayloadEXT中traceRayEXT(topLevelAS, gl_RayFlagsOpaqueEXT, 0xff, 0, 0, 0, origin.xyz, tmin, direction.xyz, tmax, 0);//将所有光线命中的点存储在图片中imageStore(image, ivec2(gl_LaunchIDEXT.xy), vec4(hitValue, 0.0)); }
miss.rmiss:
#version 460 #extension GL_EXT_ray_tracing : enable //没太看明白, 应该是,如果射线与加速结构不相交,给一个默认值 layout(location = 0) rayPayloadInEXT vec3 hitValue;void main() {hitValue = vec3(0.0, 0.0, 0.2); }
closesthit.rchit
#version 460
#extension GL_EXT_ray_tracing : enable
#extension GL_EXT_nonuniform_qualifier : enable
//如果命中输出局部重心坐标的值
layout(location = 0) rayPayloadInEXT vec3 hitValue;
//命中点的局部重心坐标信息
hitAttributeEXT vec3 attribs;void main()
{const vec3 barycentricCoords = vec3(1.0f - attribs.x - attribs.y, attribs.x, attribs.y);hitValue = barycentricCoords;
}
小结
这节主要将vulkan光追加速结构的设置方法,以及如何使用shader计算hit点。感觉封装的有点严重。但是大概能理解实现原理。从shader中只能看出,这里只是输出从渲染图像中,从每个像素发射射线所命中模型面片位置的局部中心坐标信息。至于如何渲染出最终结果这里还看不出来。估计这里只是把局部重心坐标的值作为颜色输出了(确定了, 就是这样子。 在miss阶段给了z的值为0.2,正是渲染结果的背景色)。
Ray Traced Shadows
prepare
- createBottomLevelAccelerationStructure: 在本地创建模型底层加速结构信息
- loadFromFile:加载模型
- 创建两个VkDeviceOrHostAddressConstKHR,分别存放vbo和ibo的指针(deviceAddress)
- vertexBufferDeviceAddress : getBufferDeviceAddress
- indexBufferDeviceAddress: getBufferDeviceAddress
- 创建加速结构
- VkAccelerationStructureGeometryKHR
- 参数数模型的一些基本属性
- VkAccelerationStructureBuildGeometryInfoKHR: 几何信息
- VkAccelerationStructureBuildSizesInfoKHR:Get size info
- vkGetAccelerationStructureBuildSizesKHR
- createAccelerationStructure: 创建加速结构buffer
- VkBufferCreateInfo:特殊的参数
- sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO
- usage = VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR
- vkCreateBuffer: 下面使用的参数结构体都使用加速结构相关参数
- vkGetBufferMemoryRequirements
- vkAllocateMemory
- vkBindBufferMemory
- VkAccelerationStructureCreateInfoKHR
- vkCreateAccelerationStructureKHR: 创建加速结构
- vkGetAccelerationStructureDeviceAddressKHR: AS device address
- VkBufferCreateInfo:特殊的参数
- VkAccelerationStructureGeometryKHR
- createScratchBuffer
- 在构建底层加速结构的过程中创建一个小的scratch缓冲区
- VkAccelerationStructureBuildGeometryInfoKHR:
- VkAccelerationStructureBuildRangeInfoKHR
- accelerationStructureFeatures.accelerationStructureHostCommands
- 是
- vkBuildAccelerationStructuresKHR
- 否
- createCommandBuffer
- vkCmdBuildAccelerationStructuresKHR
- flushCommandBuffer
- 是
- deleteScratchBuffer
- createTopLevelAccelerationStructure
- 创建 top level 加速结构
- VkAccelerationStructureInstanceKHR
- createBuffer: for instance data
- VkDeviceOrHostAddressConstKHR
- getBufferDeviceAddress
- VkAccelerationStructureGeometryKHR
- VkAccelerationStructureBuildGeometryInfoKHR
- VkAccelerationStructureBuildSizesInfoKHR
- vkGetAccelerationStructureBuildSizesKHR
- createAccelerationStructure()
- createScratchBuffer ()
- VkAccelerationStructureBuildGeometryInfoKHR
- VkAccelerationStructureBuildGeometryInfoKHR
- VkAccelerationStructureBuildRangeInfoKHR
- accelerationStructureFeatures.accelerationStructureHostCommands
- 是
- vkBuildAccelerationStructuresKHR
- 否
- createCommandBuffer
- vkCmdBuildAccelerationStructuresKHR
- flushCommandBuffer
- 是
- deleteScratchBuffer
- instancesBuffer.destroy()
- createStorageImage(): 存放光追渲染结果:
- VkImageCreateInfo image = vks::initializers::imageCreateInfo();
- vkCreateImage
- vkGetImageMemoryRequirements
- vkAllocateMemory
- vkBindImageMemory
- VkImageViewCreateInfo
- vkCreateImageView
- createCommandBuffer
- setImageLayout
- flushCommandBuffer - createUniformBuffer
- createBuffer
- updateUniformBuffers
- createRayTracingPipeline
- VkDescriptorSetLayoutBinding:结构体
- VkDescriptorSetLayoutCreateInfo:结构体
- vkCreateDescriptorSetLayout
- VkPipelineLayoutCreateInfo
- vkCreatePipelineLayout
- Setup ray tracing shader groups
- VkPipelineShaderStageCreateInfo
- Ray generation group
- VkRayTracingShaderGroupCreateInfoKHR: 结构体,存放shader和其他配置信息
- shader: raygen.rgen.spv
- VkRayTracingShaderGroupCreateInfoKHR: 结构体,存放shader和其他配置信息
- Miss group: 光追未命中
- VkRayTracingShaderGroupCreateInfoKHR
- shader: miss.rmiss.spv
- shader: Second shader for shadows
- Closest hit group: 光追命中
- VkRayTracingShaderGroupCreateInfoKHR
- shader: closesthit.rchit.spv
- Create the ray tracing pipeline
- VkRayTracingPipelineCreateInfoKHR:结构体
- vkCreateRayTracingPipelinesKHR
- createShaderBindingTable
- 创建用于加速结构的 shader 绑定表(Shader Binding Tables)-(SBT)
- vkGetRayTracingShaderGroupHandlesKHR
- createShaderBindingTable:创建三个SBT
- createBuffer: 创建SBT – raygen
- 使用字段VK_BUFFER_USAGE_SHADER_BINDING_TABLE_BIT_KHR
- createBuffer: miss
- createBuffer: hit
- memcpy
- memcpy
- memcpy
- createBuffer: 创建SBT – raygen
- createDescriptorSets
- vkCreateDescriptorPool
- vkAllocateDescriptorSets
- writeDescriptorSet: Ray tracing result image
- writeDescriptorSet: Uniform data
- writeDescriptorSet: Scene vertex buffer
- writeDescriptorSet: Scene index buffer
- vkUpdateDescriptorSets
- buildCommandBuffers
- handleResize
- createStorageImage
- storageImageDescriptor
- writeDescriptorSet
- vkBeginCommandBuffer
- vkCmdBindPipeline
- vkCmdBindDescriptorSets
- vkCmdTraceRaysKHR
- Copy ray tracing output to swap chain image
- setImageLayout
- setImageLayout
- vkCmdCopyImage
- setImageLayout
- setImageLayout
- vkEndCommandBuffer
- handleResize
render
- draw
- prepareFrame
- vkQueueSubmit
- submitFrame
- updateUniformBuffers
shader
raygen.rgen:计算与顶层加速结构碰撞的点
- #extension GL_EXT_ray_tracing : enable
//需要绑定topLevel的加速结构 layout(binding = 0, set = 0) uniform accelerationStructureEXT topLevelAS; layout(binding = 1, set = 0, rgba8) uniform image2D image; layout(binding = 2, set = 0) uniform CameraProperties
- layout(location = 0) rayPayloadEXT vec3 hitValue;
- 射线Hit的坐标信息
void main() {//获取像素中心像素值const vec2 pixelCenter = vec2(gl_LaunchIDEXT.xy) + vec2(0.5);//获取获取中心像素对于的uv值const vec2 inUV = pixelCenter/vec2(gl_LaunchSizeEXT.xy);vec2 d = inUV * 2.0 - 1.0;//获取射线的原点,和出射方向vec4 origin = cam.viewInverse * vec4(0,0,0,1);vec4 target = cam.projInverse * vec4(d.x, d.y, 1, 1) ;vec4 direction = cam.viewInverse*vec4(normalize(target.xyz), 0) ;//设置射线t的值范围float tmin = 0.001;float tmax = 10000.0;hitValue = vec3(0.0);//根据topLevel加速结构和射线获取与加速结构碰撞的点坐标//猜测traceRayEXT的结果存储在rayPayloadEXT中traceRayEXT(topLevelAS, gl_RayFlagsOpaqueEXT, 0xff, 0, 0, 0, origin.xyz, tmin, direction.xyz, tmax, 0);//将所有光线命中的点存储在图片中imageStore(image, ivec2(gl_LaunchIDEXT.xy), vec4(hitValue, 0.0)); }
miss.rmiss:
#version 460 #extension GL_EXT_ray_tracing : enable layout(location = 0) rayPayloadInEXT vec3 hitValue;void main() {hitValue = vec3(0.0, 0.0, 0.2); }
shadow.rmiss:
#version 460
#extension GL_EXT_ray_tracing : requirelayout(location = 2) rayPayloadInEXT bool shadowed;void main()
{shadowed = false;
}
- closesthit.rchit
#version 460
#extension GL_EXT_ray_tracing : require
#extension GL_EXT_nonuniform_qualifier : enablelayout(location = 0) rayPayloadInEXT vec3 hitValue;
layout(location = 2) rayPayloadEXT bool shadowed;
hitAttributeEXT vec3 attribs;layout(binding = 0, set = 0) uniform accelerationStructureEXT topLevelAS;
layout(binding = 2, set = 0) uniform UBO
{mat4 viewInverse;mat4 projInverse;vec4 lightPos;int vertexSize;
} ubo;
layout(binding = 3, set = 0) buffer Vertices { vec4 v[]; } vertices;
layout(binding = 4, set = 0) buffer Indices { uint i[]; } indices;struct Vertex
{vec3 pos;vec3 normal;vec2 uv;vec4 color;vec4 _pad0;vec4 _pad1;};Vertex unpack(uint index)
{// Unpack the vertices from the SSBO using the glTF vertex structure// The multiplier is the size of the vertex divided by four float components (=16 bytes)const int m = ubo.vertexSize / 16;vec4 d0 = vertices.v[m * index + 0];vec4 d1 = vertices.v[m * index + 1];vec4 d2 = vertices.v[m * index + 2];Vertex v;v.pos = d0.xyz;v.normal = vec3(d0.w, d1.x, d1.y);v.color = vec4(d2.x, d2.y, d2.z, 1.0);return v;
}void main()
{//获取当前模型面片索引ivec3 index = ivec3(indices.i[3 * gl_PrimitiveID], indices.i[3 * gl_PrimitiveID + 1], indices.i[3 * gl_PrimitiveID + 2]);//获取模型顶点的所有信息Vertex v0 = unpack(index.x);Vertex v1 = unpack(index.y);Vertex v2 = unpack(index.z);// Interpolate normal//计算hit点的重心坐标const vec3 barycentricCoords = vec3(1.0f - attribs.x - attribs.y, attribs.x, attribs.y);//根据重心坐标计算hit处的法线vec3 normal = normalize(v0.normal * barycentricCoords.x + v1.normal * barycentricCoords.y + v2.normal * barycentricCoords.z);// Basic lightingvec3 lightVector = normalize(ubo.lightPos.xyz);float dot_product = max(dot(lightVector, normal), 0.2);//获取hit处的base colorhitValue = v0.color.rgb * dot_product;// Shadow castingfloat tmin = 0.001;float tmax = 10000.0;//获取hit顶点数据: 射线原点 + 时间*方向vec3 origin = gl_WorldRayOriginEXT + gl_WorldRayDirectionEXT * gl_HitTEXT;shadowed = true; //再次使用traceRayEXT方法计算是否有阴影// gl_RayFlagsTerminateOnFirstHitEXT , 第一次命中的点// gl_RayFlagsOpaqueEXT : 是否有透明材质// gl_RayFlagsSkipClosestHitShaderEXT: 跳过已命中的点// lightVector: 是否有阴影射线方向是光源的方向// Trace shadow ray and offset indices to match shadow hit/miss shader group indicestraceRayEXT(topLevelAS, gl_RayFlagsTerminateOnFirstHitEXT | gl_RayFlagsOpaqueEXT | gl_RayFlagsSkipClosestHitShaderEXT, 0xFF, 1, 0, 1, origin, tmin, lightVector, tmax, 2);if (shadowed) {hitValue *= 0.3;}
}
小结
这节主要将vulkan光追阴影处理的方式, 感觉计算阴影的方法比较暴力, 直接在hit出发射出一条指向光源的光线, 如果命中就是存在阴影. 总体来看, vulkan 封装了光追的方法, 实现光追只需使用好这三个shader即可.
Vulkan Samples 阅读 -- Hardware Accelerated Ray Tracing(一) Basic Ray Tracing Ray Traced Shadows相关推荐
- Vulkan Samples 阅读 -- Extensions(二)
目录 Conditional Rendering prepare render shader 小结 Debug Markers Negative Viewport Height prepare ren ...
- Ray入门指南(1)----ray分布式框架的介绍
使用ray,你需要解决以下两个问题: 1.ray执行异步任务时是怎样实现平行的.(ray集群中每个节点共享本节点本地存储,节点中worker并行运行,集群间worker的并行) 2.ray是怎样使用对 ...
- Ray入门指南(2)----Ray API
Ray API 此篇主要介绍Ray的API.主要有两部分,一部分是ray再python代码中的应用:另一部分是ray在命令行中的应用. ray.init(redis_address=None, num ...
- Your WebGL implementation doesn't seem to support hardware accelerated rendering. Check your browser
报错原因 电脑不支持gpu硬件加速 首先检查电脑是否支持硬件加速,检查方法见以下链接 https://jingyan.baidu.com/article/148a1921f009fb4d70c3b17 ...
- CSS开启硬件加速 hardware accelerated
作者:孙志勇 微博 日期:2016年12月6日 一.时效性 所有信息都具有时效性.文章的价值,往往跟时间有很大关联.特别是技术类文章,请注意本文创建时间,如果本文过于久远,请读者酌情考量,莫要浪费时间 ...
- 【Vulkan】Sparse Resources(一)【Basic】
Vulkan Sparse Resources(一)[Basic] 资源定义 Sparse 资源简介 Sparse 资源特性 sparseBinding sparseResidency sparseR ...
- Arduino文档阅读笔记-4 WHEEL ROBOT CAR BASIC EXAMPLE
Arduino小车有很多种,包括2个轮子,4个轮子.都有. 下面这个实例来做一个最基础的4轮小车,下面将说明各个功能和代码. 首先得先准备这样的一辆4个轮子的小车. 再选这样的一个扩展板: 电机控制板 ...
- 《Ray Tracing in One Weekend》阅读笔记 - 5、表面法线和多个物体
对于表面法向量的设计决策,有两个要考虑的问题: 1.是否要用单位长度 "首先是这些法线是否为单位长度.这对于阴影很方便,所以我会说yes,但我不会在代码中执行它.这可能会出现一些细微的bug ...
- 总结《Ray Tracing from the Ground Up》
之前已经学习过<Ray Tracing in One Weekend>和<An Introduction to Ray Tracing>的一些内容,相关总结文档链接如下: 总结 ...
最新文章
- k8s组件批量启动、查看状态
- [bzoj 5332][SDOI2018]旧试题
- ITK:遮罩图像的归一化相关性
- Ionic(ionicframework)一款接近原生的Html5移动App开发框架 中文网
- windows渗透大全
- samba 实现不同操作系统之间的文件共享
- php启用openssl,php怎么开启openssl模块
- 盘点大型分布式网站术语
- React Native使用指南-使用链接库
- net 进阶学习 WebApi (2)
- [大数据之Sqoop] —— 什么是Sqoop?
- 嵩天《Python网络爬虫与信息提取》实例4:股票数据定向爬虫
- ubuntu使用byzanz截取gif动态图
- w ndows10图标,Win10桌面图标没了怎么办?Win10桌面快捷方式消失了解决方法
- Felix入门与实践(一)
- 杨百翰大学计算机科学专业,杨百翰大学有哪些专业_专业排名
- dfs之解救小哈-c语言
- JeeSite(2):导入数据,进入系统
- 2 Tables and Table Clusters读书笔记
- 记录一下在上海考驾照经历
热门文章
- el-tooltip disabled属性失效
- 北信科1011 K. paulzhou和方程 [组合数学+差分序列]【数学】
- Hadoop学习(11)-MapReduce的核心运行机制
- C语言模拟实现硬盘柱面访问调度算法
- Gradle开发环境配置
- 写给即将正在找工作的Android攻城狮,算法太TM重要了
- java se与jdk的关系_JDK与Java SE/EE/ME的区别
- Ubuntu安装Sublime Text 3--解决无法使用搜狗中文输入法
- 判断一个字符串是否是对称字符串
- 腾讯云短信发送(php - think PHP 6)