feat(wrapper): span-based interop, resource API refactor
Refactored native wrappers to use ReadOnlySpan<T> for pointer parameters, improving .NET safety and interop. Enhanced wrapper generator with $TYPE and prefix/suffix-based parameter remapping. Added platform-specific native library loading for meshoptimizer, nvtt, and ufbx. Updated D3D12GraphicsEngineFactory for native DLL resolution and removed redundant logic from UnitTestApp. Changed RenderGraphBuilder's resource extraction API to use QueryTextureExtraction/QueryBufferExtraction with explicit handles and flags. Removed IRenderer and D3D12Renderer, moving RenderContext to RenderPipeline. Improved mesh loading, resource management, and updated test shader conventions. Updated project references, build settings, and added launchSettings.json for tooling. BREAKING CHANGE: Native wrapper APIs now use ReadOnlySpan<T> instead of pointers. RenderGraphBuilder resource extraction API has changed. IRenderer and D3D12Renderer have been removed.
This commit is contained in:
@@ -9,7 +9,7 @@
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||
<IsAotCompatible>True</IsAotCompatible>
|
||||
<DefineConstants>$(DefineConstants);MHP_ENABLE_SAFETY_CHECKS;MHP_ENABLE_STACKTRACE</DefineConstants>
|
||||
<DefineConstants>$(DefineConstants);MHP_ENABLE_SAFETY_CHECKS</DefineConstants>
|
||||
<IsTrimmable>True</IsTrimmable>
|
||||
</PropertyGroup>
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Misaki.HighPerformance" Version="1.0.6" />
|
||||
<PackageReference Include="Misaki.HighPerformance.Jobs" Version="1.5.6" />
|
||||
<PackageReference Include="Misaki.HighPerformance.Jobs" Version="1.5.8" />
|
||||
<PackageReference Include="Misaki.HighPerformance.LowLevel" Version="1.6.3">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using Ghost.Core;
|
||||
using Ghost.Entities;
|
||||
using Ghost.Graphics.Core;
|
||||
using Ghost.Graphics.RenderPipeline;
|
||||
using Ghost.Graphics.RHI;
|
||||
using Misaki.HighPerformance.Mathematics;
|
||||
|
||||
|
||||
@@ -3,6 +3,4 @@ global using static TerraFX.Interop.DirectX.DirectX;
|
||||
global using static TerraFX.Interop.DirectX.DXGI;
|
||||
global using static TerraFX.Interop.Windows.Windows;
|
||||
|
||||
using System.Runtime.Versioning;
|
||||
|
||||
[assembly: SupportedOSPlatform("windows10.0.19041.0")]
|
||||
[assembly: System.Runtime.Versioning.SupportedOSPlatform("windows10.0.19041.0")]
|
||||
@@ -7,11 +7,38 @@ using Ghost.Graphics.Core;
|
||||
using Ghost.Graphics.RHI;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Runtime.Loader;
|
||||
|
||||
namespace Ghost.Graphics.D3D12;
|
||||
|
||||
public static class D3D12GraphicsEngineFactory
|
||||
{
|
||||
static D3D12GraphicsEngineFactory()
|
||||
{
|
||||
var currentDir = AppContext.BaseDirectory;
|
||||
var platform = OperatingSystem.IsWindows() ? "win" :
|
||||
OperatingSystem.IsLinux() ? "linux" :
|
||||
OperatingSystem.IsMacOS() ? "osx" : "unknown";
|
||||
var arch = Environment.Is64BitProcess ? "x64" : "x86";
|
||||
var nativeDllDir = Path.Combine(currentDir, "runtimes", platform + "-" + arch, "native");
|
||||
|
||||
AssemblyLoadContext.Default.ResolvingUnmanagedDll += (assembly, libraryName) =>
|
||||
{
|
||||
if (libraryName == "dxcompiler")
|
||||
{
|
||||
NativeLibrary.TryLoad(Path.Combine(nativeDllDir, "dxil.dll"), out _);
|
||||
|
||||
if (NativeLibrary.TryLoad(Path.Combine(nativeDllDir, "dxcompiler.dll"), out var dxcHandle))
|
||||
{
|
||||
return dxcHandle;
|
||||
}
|
||||
}
|
||||
|
||||
return IntPtr.Zero;
|
||||
};
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static IGraphicsEngine Create(GraphicsEngineDesc desc)
|
||||
{
|
||||
|
||||
@@ -1,124 +0,0 @@
|
||||
using Ghost.Core;
|
||||
using Ghost.Graphics.RHI;
|
||||
|
||||
namespace Ghost.Graphics.D3D12;
|
||||
|
||||
/// <summary>
|
||||
/// D3D12 implementation of the renderer interface using RHI abstractions
|
||||
/// </summary>
|
||||
internal class D3D12Renderer : IRenderer
|
||||
{
|
||||
private readonly D3D12GraphicsEngine _graphicsEngine;
|
||||
private readonly ICommandBuffer _commandBuffer;
|
||||
|
||||
private bool _disposed;
|
||||
|
||||
public IRenderOutput? RenderOutput
|
||||
{
|
||||
get; set;
|
||||
}
|
||||
|
||||
public Func<RenderContext, Error>? RenderFunc
|
||||
{
|
||||
get; set;
|
||||
}
|
||||
|
||||
public D3D12Renderer(D3D12GraphicsEngine graphicsEngine)
|
||||
{
|
||||
_graphicsEngine = graphicsEngine;
|
||||
_commandBuffer = _graphicsEngine.CreateCommandBuffer(CommandBufferType.Graphics);
|
||||
}
|
||||
|
||||
~D3D12Renderer()
|
||||
{
|
||||
Dispose();
|
||||
}
|
||||
|
||||
public Result Render(ICommandAllocator commandAllocator)
|
||||
{
|
||||
if (RenderFunc is null)
|
||||
{
|
||||
return Result.Success(); // No render function set, skip rendering.
|
||||
}
|
||||
|
||||
if (RenderOutput is null)
|
||||
{
|
||||
return Result.Failure("Render target strategy is not set.");
|
||||
}
|
||||
|
||||
var target = RenderOutput.GetRenderTarget();
|
||||
if (target.IsInvalid)
|
||||
{
|
||||
return Result.Failure("Render target is invalid.");
|
||||
}
|
||||
|
||||
_commandBuffer.Begin(commandAllocator);
|
||||
RenderOutput.BeginRender(_commandBuffer);
|
||||
|
||||
var ctx = new RenderContext();
|
||||
var error = RenderFunc.Invoke(ctx);
|
||||
if (error != Error.None)
|
||||
{
|
||||
_commandBuffer.End();
|
||||
return Result.Failure(error);
|
||||
}
|
||||
|
||||
RenderOutput.EndRender(_commandBuffer);
|
||||
var r = _commandBuffer.End();
|
||||
if (r.IsFailure)
|
||||
{
|
||||
return r;
|
||||
}
|
||||
|
||||
_graphicsEngine.Device.GraphicsQueue.Submit(_commandBuffer);
|
||||
RenderOutput.Present();
|
||||
|
||||
return Result.Success();
|
||||
}
|
||||
|
||||
//// TODO: A proper render graph integration.
|
||||
//private Error RenderScene(Handle<Texture> target, ViewportDesc viewport, ScissorRectDesc rect)
|
||||
//{
|
||||
// // NOTE: Testing only.
|
||||
// var ctx = new RenderingContext(_graphicsEngine, _commandBuffer);
|
||||
// if (_frameIndex == 0)
|
||||
// {
|
||||
// _pass.Initialize(ref ctx);
|
||||
// }
|
||||
|
||||
// //_commandBuffer.BeginRenderPass(rtDesc, depthDesc, false);
|
||||
// _commandBuffer.SetViewport(viewport);
|
||||
// _commandBuffer.SetScissorRect(rect);
|
||||
|
||||
// _renderGraph.Reset();
|
||||
|
||||
// var backBuffer = _renderGraph.ImportTexture(target, "Back Buffer");
|
||||
// _pass.Build(_renderGraph, backBuffer);
|
||||
|
||||
// // Create view state from viewport
|
||||
// var viewState = new ViewState((uint)viewport.Width, (uint)viewport.Height);
|
||||
|
||||
// // Compile with view state
|
||||
// _renderGraph.Compile(in viewState);
|
||||
// _renderGraph.Execute(_commandBuffer);
|
||||
|
||||
// //_commandBuffer.EndRenderPass();
|
||||
// _frameIndex++;
|
||||
|
||||
// return Error.None;
|
||||
//}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (_disposed)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_commandBuffer.Dispose();
|
||||
|
||||
_disposed = true;
|
||||
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
}
|
||||
@@ -487,7 +487,7 @@ internal static unsafe class D3D12Utility
|
||||
public static D3D12_RASTERIZER_DESC D3D12_RASTERIZER_DESC_CREATE(
|
||||
D3D12_FILL_MODE fillMode,
|
||||
D3D12_CULL_MODE cullMode,
|
||||
bool frontCounterClockwise = false,
|
||||
bool frontCounterClockwise = true,
|
||||
int depthBias = D3D12_DEFAULT_DEPTH_BIAS,
|
||||
float depthBiasClamp = D3D12_DEFAULT_DEPTH_BIAS_CLAMP,
|
||||
float slopeScaledDepthBias = D3D12_DEFAULT_SLOPE_SCALED_DEPTH_BIAS,
|
||||
|
||||
@@ -1,42 +0,0 @@
|
||||
using Ghost.Core;
|
||||
|
||||
namespace Ghost.Graphics.RHI;
|
||||
|
||||
public readonly struct RenderContext
|
||||
{
|
||||
public ICommandBuffer CommandBuffer { get; init; }
|
||||
public ICommandQueue GraphicsQueue { get; init; }
|
||||
public ICommandQueue ComputeQueue { get; init; }
|
||||
public ICommandQueue CopyQueue { get; init; }
|
||||
}
|
||||
|
||||
// TODO: We may don't need this anymore. We Use RenderExtractionSystem to extract render data from entities and pass them to IRenderPipeline to render.
|
||||
|
||||
/// <summary>
|
||||
/// High-level renderer interface that uses RHI abstractions
|
||||
/// </summary>
|
||||
public interface IRenderer : IDisposable
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the render output target for this renderer.
|
||||
/// </summary>
|
||||
IRenderOutput? RenderOutput
|
||||
{
|
||||
get; set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The function that performs the actual rendering operations. Skip rendering if this is null.
|
||||
/// </summary>
|
||||
Func<RenderContext, Error>? RenderFunc
|
||||
{
|
||||
get; set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Renders a frame
|
||||
/// </summary>
|
||||
/// <param name="commandAllocator">Command allocator to use for rendering</param>
|
||||
/// <returns>Result of the rendering operation</returns>
|
||||
Result Render(ICommandAllocator commandAllocator);
|
||||
}
|
||||
@@ -1,9 +1,9 @@
|
||||
using Ghost.Core;
|
||||
using Ghost.Graphics.RHI;
|
||||
using Ghost.Graphics.Utilities;
|
||||
using Misaki.HighPerformance.Jobs;
|
||||
using Misaki.HighPerformance.LowLevel.Buffer;
|
||||
using Misaki.HighPerformance.LowLevel.Collections;
|
||||
using Misaki.HighPerformance.LowLevel.Utilities;
|
||||
using Misaki.HighPerformance.Mathematics;
|
||||
using Misaki.HighPerformance.Mathematics.Geometry;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
@@ -246,6 +246,7 @@ public struct Mesh : IResourceReleasable
|
||||
private static unsafe int MeshletOutputCallback(void* context, ClodGroup group, ReadOnlyUnsafeCollection<ClodCluster> clusters)
|
||||
{
|
||||
var mesh = (Mesh*)context;
|
||||
|
||||
ref var data = ref mesh->_meshletData;
|
||||
|
||||
// Ensure lists are initialized
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Ghost.Core;
|
||||
using Ghost.Graphics.RenderPipeline;
|
||||
using Ghost.Graphics.RHI;
|
||||
using Misaki.HighPerformance.Mathematics;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
@@ -2,8 +2,6 @@ using Ghost.Core;
|
||||
using Ghost.Graphics.RHI;
|
||||
using Misaki.HighPerformance.LowLevel.Buffer;
|
||||
using Misaki.HighPerformance.LowLevel.Collections;
|
||||
using Misaki.HighPerformance.LowLevel.Utilities;
|
||||
using Misaki.HighPerformance.Mathematics;
|
||||
|
||||
namespace Ghost.Graphics.Core;
|
||||
|
||||
|
||||
@@ -17,6 +17,16 @@ public enum AccessFlags : byte
|
||||
ReadWrite = Read | Write,
|
||||
}
|
||||
|
||||
[Flags]
|
||||
public enum ResourceExtractionFlags : byte
|
||||
{
|
||||
None = 0,
|
||||
/// <summary>
|
||||
/// Releases the old resource after extraction.
|
||||
/// </summary>
|
||||
ReleaseAfterExtract = 1 << 0,
|
||||
}
|
||||
|
||||
public interface IRenderGraphBuilder : IDisposable
|
||||
{
|
||||
/// <summary>
|
||||
@@ -33,17 +43,6 @@ public interface IRenderGraphBuilder : IDisposable
|
||||
/// <returns>An identifier for the newly created texture resource.</returns>
|
||||
Identifier<RGTexture> CreateTexture(in RGTextureDesc desc, string name);
|
||||
|
||||
/// <summary>
|
||||
/// Creates multiple texture resources based on the specified desc.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Those textures will be used as multi buffering in the render graph automaticlly and not aliasable with other resources.
|
||||
/// </remarks>
|
||||
/// <param name="desc">A structure that defines the properties and configuration of the texture to create.</param>
|
||||
/// <param name="name">The base name of the texture resources. The actual name for each texture will be generated by appending an index to this base name.</param>
|
||||
/// <param name="textureIDs">A span to receive the identifiers for the newly created texture resources. The length of the span determines how many textures will be created.</param>
|
||||
void CreateTextures(in RGTextureDesc desc, string name, Span<Identifier<RGTexture>> textureIDs);
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new buffer resource based on the specified desc.
|
||||
/// </summary>
|
||||
@@ -52,17 +51,6 @@ public interface IRenderGraphBuilder : IDisposable
|
||||
/// <returns>An identifier for the newly created buffer resource.</returns>
|
||||
Identifier<RGBuffer> CreateBuffer(in BufferDesc desc, string name);
|
||||
|
||||
/// <summary>
|
||||
/// Creates multiple buffer resources based on the specified desc.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Those buffers will be used as multi buffering in the render graph automaticlly and not aliasable with other resources.
|
||||
/// </remarks>
|
||||
/// <param name="desc">A structure that defines the properties and configuration of the buffer to create.</param>
|
||||
/// <param name="name">The base name of the buffer resources. The actual name for each buffer will be generated by appending an index to this base name.</param>
|
||||
/// <param name="bufferIDs">A span to receive the identifiers for the newly created buffer resources. The length of the span determines how many buffers will be created.</param>
|
||||
void CreateBuffers(in BufferDesc desc, string name, Span<Identifier<RGBuffer>> bufferIDs);
|
||||
|
||||
/// <summary>
|
||||
/// Registers the specified texture for use in the current render graph pass with the given access mode.
|
||||
/// </summary>
|
||||
@@ -83,16 +71,16 @@ public interface IRenderGraphBuilder : IDisposable
|
||||
/// <summary>
|
||||
/// Extracts the actual texture resource associated with the given identifier for use in outside of the render graph execution context.
|
||||
/// </summary>
|
||||
/// <param name="texture">The identifier of the texture to be extracted.</param>
|
||||
/// <returns>A handle to the actual texture resource that can be used outside of the render graph execution context.</returns>
|
||||
Handle<GPUTexture> ExtractTexture(Identifier<RGTexture> texture);
|
||||
/// <param name="src">The identifier of the texture to be extracted.</param>
|
||||
/// <param name="dst">A handle to receive the actual GPU texture resource.</param>
|
||||
void QueryTextureExtraction(Identifier<RGTexture> src, Handle<GPUTexture> dst, ResourceExtractionFlags flags = ResourceExtractionFlags.ReleaseAfterExtract);
|
||||
|
||||
/// <summary>
|
||||
/// Extracts the actual buffer resource associated with the given identifier for use in outside of the render graph execution context.
|
||||
/// </summary>
|
||||
/// <param name="buffer">The identifier of the buffer to be extracted.</param>
|
||||
/// <returns>A handle to the actual buffer resource that can be used outside of the render graph execution context.</returns>
|
||||
Handle<GPUBuffer> ExtractBuffer(Identifier<RGBuffer> buffer);
|
||||
/// <param name="src">The identifier of the buffer to be extracted.</param>
|
||||
/// <param name="dst">A handle to receive the actual GPU buffer resource.</param>
|
||||
void QueryBufferExtraction(Identifier<RGBuffer> src, Handle<GPUBuffer> dst, ResourceExtractionFlags flags = ResourceExtractionFlags.ReleaseAfterExtract);
|
||||
}
|
||||
|
||||
public interface IRasterRenderGraphBuilder : IRenderGraphBuilder
|
||||
@@ -244,18 +232,6 @@ internal class RenderGraphBuilder : IRasterRenderGraphBuilder, IComputeRenderGra
|
||||
return handle;
|
||||
}
|
||||
|
||||
public void CreateTextures(in RGTextureDesc desc, string name, Span<Identifier<RGTexture>> textureIDs)
|
||||
{
|
||||
// TODO: Create multiple textures, mark them as no aliasable, and add them to the resource registry and current pass.
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void CreateBuffers(in BufferDesc desc, string name, Span<Identifier<RGBuffer>> bufferIDs)
|
||||
{
|
||||
// TODO: Create multiple buffers, mark them as no aliasable, and add them to the resource registry and current pass.
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Identifier<RGTexture> UseTexture(Identifier<RGTexture> texture, AccessFlags flags)
|
||||
{
|
||||
ThrowIfDisposed();
|
||||
@@ -268,13 +244,13 @@ internal class RenderGraphBuilder : IRasterRenderGraphBuilder, IComputeRenderGra
|
||||
return UseResource(buffer.AsResource(), flags, RenderGraphResourceType.Buffer).AsBuffer();
|
||||
}
|
||||
|
||||
// TODO: Implement ExtractTexture and ExtractBuffer to allow users to get the actual GPU resources for use outside of the render graph execution context.
|
||||
public Handle<GPUTexture> ExtractTexture(Identifier<RGTexture> texture)
|
||||
// TODO: Implement QueryTextureExtraction and QueryBufferExtraction to allow users to get the actual GPU resources for use outside of the render graph execution context.
|
||||
public void QueryTextureExtraction(Identifier<RGTexture> src, Handle<GPUTexture> dst, ResourceExtractionFlags flags = ResourceExtractionFlags.ReleaseAfterExtract)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Handle<GPUBuffer> ExtractBuffer(Identifier<RGBuffer> buffer)
|
||||
public void QueryBufferExtraction(Identifier<RGBuffer> src, Handle<GPUBuffer> dst, ResourceExtractionFlags flags = ResourceExtractionFlags.ReleaseAfterExtract)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
@@ -3,6 +3,14 @@ using Ghost.Graphics.RHI;
|
||||
|
||||
namespace Ghost.Graphics.RenderPipeline;
|
||||
|
||||
public readonly struct RenderContext
|
||||
{
|
||||
public ICommandBuffer CommandBuffer { get; init; }
|
||||
public ICommandQueue GraphicsQueue { get; init; }
|
||||
public ICommandQueue ComputeQueue { get; init; }
|
||||
public ICommandQueue CopyQueue { get; init; }
|
||||
}
|
||||
|
||||
public interface IRenderPipelineSettings
|
||||
{
|
||||
IRenderPipeline CreatePipeline(RenderSystem renderSystem);
|
||||
|
||||
@@ -205,7 +205,8 @@ public sealed class ResourceManager : IDisposable
|
||||
{
|
||||
Debug.Assert(!_disposed);
|
||||
|
||||
if (!_meshes.TryGetElementAt(handle.ID, handle.Generation, out var mesh))
|
||||
ref var mesh = ref _meshes.GetElementReferenceAt(handle.ID, handle.Generation, out var exist);
|
||||
if (!exist)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -249,7 +250,7 @@ public sealed class ResourceManager : IDisposable
|
||||
{
|
||||
Debug.Assert(!_disposed);
|
||||
|
||||
var material = _materials.GetElementReferenceAt(handle.ID, handle.Generation, out var exist);
|
||||
ref var material = ref _materials.GetElementReferenceAt(handle.ID, handle.Generation, out var exist);
|
||||
if (!exist)
|
||||
{
|
||||
return;
|
||||
@@ -359,7 +360,7 @@ public sealed class ResourceManager : IDisposable
|
||||
return;
|
||||
}
|
||||
|
||||
var shader = _shaders[id.Value];
|
||||
ref var shader = ref _shaders[id.Value];
|
||||
shader.ReleaseResource(_resourceDatabase);
|
||||
}
|
||||
|
||||
@@ -402,17 +403,17 @@ public sealed class ResourceManager : IDisposable
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var mesh in _meshes)
|
||||
foreach (ref var mesh in _meshes)
|
||||
{
|
||||
mesh.ReleaseResource(_resourceDatabase);
|
||||
}
|
||||
|
||||
foreach (var material in _materials)
|
||||
foreach (ref var material in _materials)
|
||||
{
|
||||
material.ReleaseResource(_resourceDatabase);
|
||||
}
|
||||
|
||||
foreach (var shader in _shaders)
|
||||
foreach (ref var shader in _shaders)
|
||||
{
|
||||
shader.ReleaseResource(_resourceDatabase);
|
||||
}
|
||||
|
||||
@@ -14,9 +14,9 @@ shader "MyShader/Standard"
|
||||
{
|
||||
pipeline
|
||||
{
|
||||
ztest = disabled;
|
||||
zwrite = off;
|
||||
cull = off;
|
||||
ztest = less_equal;
|
||||
zwrite = on;
|
||||
cull = back;
|
||||
blend = opaque;
|
||||
color_mask = all;
|
||||
}
|
||||
@@ -34,6 +34,7 @@ shader "MyShader/Standard"
|
||||
{
|
||||
float4 position : SV_POSITION;
|
||||
float4 color : COLOR;
|
||||
float3 normal : NORMAL;
|
||||
float2 uv : TEXCOORD0;
|
||||
nointerpolation uint meshletID : MESHLET_ID;
|
||||
};
|
||||
@@ -78,6 +79,7 @@ shader "MyShader/Standard"
|
||||
// outVerts[groupThreadID.x].position = v.position.xyz;
|
||||
|
||||
outVerts[groupThreadID.x].color = v.color;
|
||||
outVerts[groupThreadID.x].normal = normalize(mul((float3x3)instanceData.localToWorld, v.normal));
|
||||
outVerts[groupThreadID.x].uv = v.uv;
|
||||
outVerts[groupThreadID.x].meshletID = groupID.x;
|
||||
}
|
||||
@@ -110,13 +112,14 @@ shader "MyShader/Standard"
|
||||
// float4 blendedColor = (color1 + color2 + color3 + color4) * 0.25f;
|
||||
// return perMaterialData.color * blendedColor + input.color;
|
||||
|
||||
uint hash = PCGHash(input.meshletID);
|
||||
|
||||
float r = float((hash & 0xFF0000u) >> 16) / 255.0;
|
||||
float g = float((hash & 0x00FF00u) >> 8) / 255.0;
|
||||
float b = float((hash & 0x0000FFu)) / 255.0;
|
||||
|
||||
return float4(r, g, b, 1.0);
|
||||
// uint hash = PCGHash(input.meshletID);
|
||||
//
|
||||
// float r = float((hash & 0xFF0000u) >> 16) / 255.0;
|
||||
// float g = float((hash & 0x00FF00u) >> 8) / 255.0;
|
||||
// float b = float((hash & 0x0000FFu)) / 255.0;
|
||||
//
|
||||
// return float4(r, g, b, 1.0);
|
||||
return float4(input.normal, 1.0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user