Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Post
  • Reply
fankey
Aug 31, 2001

I have a 'terrain' mesh - not actually a terrian but a 2d grid of points equally spaced in the x and z dimensions. I'm assigning the y value to visualize some real time data. I'd like to assign colors which indicate the height - something like this



What would be the most efficient way to accomplish this? I'm using the 3d stuff built into WPF which might limit the approaches I can take.

Adbot
ADBOT LOVES YOU

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.

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

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.

fankey
Aug 31, 2001

Absurd Alhazred posted:

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!

  • 1
  • 2
  • 3
  • 4
  • 5
  • Post
  • Reply