- Adbot
-
ADBOT LOVES YOU
|
|
#
¿
Apr 29, 2024 16:26
|
|
- fankey
- Aug 31, 2001
-
|
OneEightHundred posted:
Option A: Make a 2D texture, colorize it based on the height, and assign the texture coordinates of the "terrain" mesh to the corresponding locations on that texture.
Option B: Make a 1D texture containing the colors in order, and reference it based on height.
Thanks, Option B appears to work pretty well. It doesn't look like WPF has a concept of vertex color so I wasn't able to use that approach. Luckily this isn't true scientific visualization - it's for real time audio acoustical measurements so the specific colors used don't need to be 100% accurate.
|
#
¿
Sep 8, 2009 20:31
|
|
- fankey
- Aug 31, 2001
-
|
Not really a 3d question but this is probably the right place to ask this question. I'm trying to encode a series of IDXGISurfaces with an IMFSinkWriter. Here's my encoder implementation:
code:#pragma once
#define NOMINMAX
#include <windows.h>
#include <d3d11_2.h>
#include <mfidl.h>
#include <mfreadwrite.h>
#include <wrl.h>
class Encoder
{
Microsoft::WRL::ComPtr<IMFMediaType> mediaTypeOut;
Microsoft::WRL::ComPtr<IMFMediaType> mediaTypeIn;
Microsoft::WRL::ComPtr<IMFSinkWriter> writer;
DWORD streamIndex{ 0 };
DWORD frame{ 0 };
public:
Encoder();
void AddFrame(_In_ Microsoft::WRL::ComPtr<IDXGISurface> surf);
void Save();
};
code:#include "encoder.h"
#include <comdef.h>
#include <iostream>
#include <mfapi.h>
#pragma comment(lib, "mf.lib")
#pragma comment(lib, "mfplat.lib")
#pragma comment(lib, "mfuuid.lib")
#pragma comment(lib, "Mfreadwrite.lib")
#pragma comment(lib, "dxguid.lib")
using namespace std;
using namespace Microsoft::WRL;
const UINT32 VIDEO_WIDTH = 1024;
const UINT32 VIDEO_HEIGHT = 768;
const UINT32 VIDEO_FPS = 30;
const UINT64 VIDEO_FRAME_DURATION = 10 * 1000 * 1000 / VIDEO_FPS;
const UINT32 VIDEO_BIT_RATE = 800000;
const GUID VIDEO_ENCODING_FORMAT = MFVideoFormat_WMV3;
const GUID VIDEO_INPUT_FORMAT = MFVideoFormat_RGB32;
class ComException : public std::exception
{
public:
ComException(HRESULT errorCode, const std::string& message) :
errorCode(errorCode),
message(message)
{}
friend std::ostream& operator<<(std::ostream& s, const ComException& e)
{
_com_error comError(e.errorCode);
char msg[512];
size_t length;
wcstombs_s(&length, msg, 512, comError.ErrorMessage(), _TRUNCATE);
return s << "Error in '" << e.message << "': 0x" << std::hex << e.errorCode << " - " << std::string(msg,length);
}
private:
HRESULT errorCode;
std::string message;
};
#define THROW_ON_FAIL(expr) { \
HRESULT _errorCode = expr; \
if(FAILED(_errorCode)) throw ComException(_errorCode, #expr); \
}
Encoder::Encoder()
{
try
{
MFStartup(MF_VERSION);
THROW_ON_FAIL(MFCreateSinkWriterFromURL(
L"c:\\logs\\output.wmv",
NULL,
NULL,
&writer));
// set output type
THROW_ON_FAIL(MFCreateMediaType(&mediaTypeOut));
THROW_ON_FAIL(mediaTypeOut->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video));
THROW_ON_FAIL(mediaTypeOut->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_H264));
THROW_ON_FAIL(mediaTypeOut->SetUINT32(MF_MT_AVG_BITRATE, VIDEO_BIT_RATE));
THROW_ON_FAIL(mediaTypeOut->SetUINT32(MF_MT_INTERLACE_MODE, MFVideoInterlace_Progressive));
THROW_ON_FAIL(MFSetAttributeSize(mediaTypeOut.Get(), MF_MT_FRAME_SIZE, VIDEO_WIDTH, VIDEO_HEIGHT));
THROW_ON_FAIL(MFSetAttributeRatio(mediaTypeOut.Get(), MF_MT_FRAME_RATE, VIDEO_FPS, 1));
THROW_ON_FAIL(MFSetAttributeRatio(mediaTypeOut.Get(), MF_MT_PIXEL_ASPECT_RATIO, 1, 1));
THROW_ON_FAIL(writer->AddStream(mediaTypeOut.Get(), &streamIndex));
// Set the input media type.
THROW_ON_FAIL(MFCreateMediaType(&mediaTypeIn));
THROW_ON_FAIL(mediaTypeIn->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video));
THROW_ON_FAIL(mediaTypeIn->SetGUID(MF_MT_SUBTYPE, VIDEO_INPUT_FORMAT));
THROW_ON_FAIL(mediaTypeIn->SetUINT32(MF_MT_INTERLACE_MODE, MFVideoInterlace_Progressive));
THROW_ON_FAIL(MFSetAttributeSize(mediaTypeIn.Get(), MF_MT_FRAME_SIZE, VIDEO_WIDTH, VIDEO_HEIGHT));
THROW_ON_FAIL(MFSetAttributeRatio(mediaTypeIn.Get(), MF_MT_FRAME_RATE, VIDEO_FPS, 1));
THROW_ON_FAIL(MFSetAttributeRatio(mediaTypeIn.Get(), MF_MT_PIXEL_ASPECT_RATIO, 1, 1));
THROW_ON_FAIL(writer->SetInputMediaType(streamIndex, mediaTypeIn.Get(), NULL));
writer->BeginWriting();
}
catch(ComException ex)
{
std::cout << ex;
}
}
void Encoder::AddFrame(_In_ Microsoft::WRL::ComPtr<IDXGISurface> surf)
{
try
{
DXGI_SURFACE_DESC desc;
THROW_ON_FAIL(surf->GetDesc(&desc));
std::cout << "w: " << desc.Width << " h: " << desc.Height << " format " << desc.Format << std::endl;
ComPtr<IMFSample> sample;
ComPtr<IMFMediaBuffer> buffer;
THROW_ON_FAIL(MFCreateDXGISurfaceBuffer(
IID_ID3D11Texture2D,
surf.Get(),
0,
FALSE,
&buffer));
THROW_ON_FAIL(MFCreateSample(&sample));
THROW_ON_FAIL(sample->AddBuffer(buffer.Get()));
THROW_ON_FAIL(sample->SetSampleTime(frame * VIDEO_FRAME_DURATION));
THROW_ON_FAIL(sample->SetSampleDuration(VIDEO_FRAME_DURATION));
THROW_ON_FAIL(writer->WriteSample(streamIndex, sample.Get()));
std::cout << "wrote ok" << std::endl;
}
catch (ComException ex)
{
std::cout << ex << std::endl;
}
frame++;
}
void Encoder::Save()
{
writer->Flush(streamIndex);
}
The code runs fine without any errors up until the writer->WriteSample call - that returns an Invalid Parameter error. I've verified that the size and format of the surface matches the size and format of the input media type. I've enabled DirectX debug messages and don't see anything of interest printed there. Any idea what might be causing this issue? Any way to better narrow it down?
For some context - my end goal is to encode an IddCx virtual display which has SwapChain that supplies the IDXGISurface. Since developing and debugging drivers is painful at best I want to prove out my encoder on a simple desktop app. Since I have 0 experience with DirectX I found a tutorial here which uses a SwapChain on a desktop app and added a call to my Encoder::AddFrame. I was able to save the contents of the IDXGISurface without any issue so I know things are working at some level.
Edit: If I create the buffer with a static block of memory like this example things work fine so it's something to do with the surface I'm trying to use.
fankey fucked around with this message at 05:12 on Nov 10, 2020
|
#
¿
Nov 10, 2020 05:01
|
|
- fankey
- Aug 31, 2001
-
|
I'm trying to write a simple HLSL 2d shader ( the end result is a WPF Effect if that matters ) that needs to deal with alpha and I am getting totally confused. This simple filter works fine and passes the color straight through
code:sampler2D input: register(s0);
float4 main(float2 uv:TEXCOORD) : COLOR
{
float4 color = tex2D(input, uv);
return color;
}
The problem is that if I modify either the alpha or the color things get wonky so I'm obviously not understanding basic concepts. I can set rgba to fixed values but attempting to do any math on them gets weird. So this works to clear out red or to adjust the alpha
code:sampler2D input: register(s0);
float4 main(float2 uv:TEXCOORD) : COLOR
{
float4 color = tex2D(input, uv);
color.rgb.r = 0;
// also this works
color.a = color.a / 2;
return color;
}
But if I try and invert a pixel things get weird. This code tries to just invert the blue channel but ends up also modifying the alpha.
code:sampler2D input: register(s0);
float4 main(float2 uv:TEXCOORD) : COLOR
{
float4 color = tex2D(input, uv);
color.b = 1.0f - color.b;
return color;
}
both
I tried saving the alpha and reapplying but it didn't make any difference.
|
#
¿
Jun 15, 2021 18:28
|
|
- fankey
- Aug 31, 2001
-
|
Have you tried dividing the color by the alpha, inverting, then multiplying by the alpha? It might be pre-multiplied and get messed up if you don't account for it.
That was it - thanks!
|
#
¿
Jun 15, 2021 19:12
|
|