Skip to content

Instantly share code, notes, and snippets.

@nomissbowling
Forked from rare25/main.cpp
Created October 24, 2020 01:03
Show Gist options
  • Save nomissbowling/0919c8c8e6f0035ef2765a79f8a66f2c to your computer and use it in GitHub Desktop.
Save nomissbowling/0919c8c8e6f0035ef2765a79f8a66f2c to your computer and use it in GitHub Desktop.
DxLibとOpenCVの動画出力サンプル
#define _CRT_SECURE_NO_WARNINGS 1
#include "DxLib.h"
#include <opencv2/opencv.hpp>
void MixSound(int main, int sub, int samplePos) {
int sampleNum = GetSoftSoundSampleNum(sub);
for (int i = 0; i < sampleNum; i++) {
int ch1 = 0;
int ch2 = 0;
int buf1;
int buf2;
ReadSoftSoundData(main, samplePos + i, &buf1, &buf2);
ch1 += buf1;
ch2 += buf2;
ReadSoftSoundData(sub, i, &buf1, &buf2);
ch1 += buf1;
ch2 += buf2;
WriteSoftSoundData(main, samplePos + i, ch1, ch2);
}
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
const int SCREEN_WIDTH = 1280;
const int SCREEN_HEIGHT = 720;
SetGraphMode(SCREEN_WIDTH, SCREEN_HEIGHT, 32);
ChangeWindowMode(TRUE);
//垂直同期をしない
SetWaitVSyncFlag(FALSE);
if (DxLib_Init())return -1;
SetDrawScreen(DX_SCREEN_BACK);
int SIHandle = MakeARGB8ColorSoftImage(SCREEN_WIDTH, SCREEN_HEIGHT);
//動画出力設定
cv::VideoWriter writer("_temp.avi", cv::VideoWriter::fourcc('M', 'J', 'P', 'G'), 60, cv::Size(SCREEN_WIDTH, SCREEN_HEIGHT));
cv::Mat frame(cv::Size(SCREEN_WIDTH, SCREEN_HEIGHT), CV_8UC4, cv::Scalar::all(0));
int USER_SCREEN_MAIN = MakeScreen(SCREEN_WIDTH, SCREEN_HEIGHT, TRUE);
int shaderHandle = LoadPixelShader("rgb2bgr.pso");
VERTEX2DSHADER vertex[4];
for (int i = 0; i < 4; i++)
{
vertex[i].pos = VGet((i % 2)*1280.0f, (i / 2)*720.0f, 0);
vertex[i].rhw = 1.0f;
vertex[i].dif = GetColorU8(255, 255, 255, 255);
vertex[i].spc = GetColorU8(0, 0, 0, 0);
vertex[i].u = vertex[i].su = (float)(i % 2);
vertex[i].v = vertex[i].sv = (float)(i / 2);
}
//サンプリングレートの変換はしていないので、違う形式を読み込むと音が正常に合成されないので注意
int musicHandle = LoadSoftSound("music.wav");
int sehandle = LoadSoftSound("tap.ogg");
//ここから音声出力コード
printfDx("MixingSound...");
ScreenFlip();
MixSound(musicHandle, sehandle, 110000);
MixSound(musicHandle, sehandle, 120000);
MixSound(musicHandle, sehandle, 130000);
MixSound(musicHandle, sehandle, 140000);
MixSound(musicHandle, sehandle, 150000);
MixSound(musicHandle, sehandle, 160000);
MixSound(musicHandle, sehandle, 170000);
//音声を保存
SaveSoftSound(musicHandle, "_temp.wav");
int frameNum = 600;
size_t memorySize = SCREEN_WIDTH * SCREEN_HEIGHT * 4;
for (int i = 0; i<frameNum; i++) {
clsDx();
ProcessMessage();
SetDrawScreen(USER_SCREEN_MAIN);
ClearDrawScreen();
//ここで描画
//ここから動画出力コード
SetDrawScreen(DX_SCREEN_BACK);
ClearDrawScreen();
//RGBからBGRにして描画
SetUseTextureToShader(0, USER_SCREEN_MAIN);
SetUsePixelShader(shaderHandle);
DrawPrimitive2DToShader(vertex, 4, DX_PRIMTYPE_TRIANGLESTRIP);
//ソフトウェアイメージに書き込み(ここの処理が重い)
GetDrawScreenSoftImage(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, SIHandle);
//ビットマップをOpenCV側のフレームにコピー(OpenCVは配置順がBGRなので上記の処理を行う)
memcpy(frame.data, GetImageAddressSoftImage(SIHandle), memorySize);
writer << frame;
//コピー後、元のRGBを描画
DrawGraph(0, 0, USER_SCREEN_MAIN, FALSE);
//情報を表示
printfDx("Writing... %d/%d", i, frameNum - 1);
ScreenFlip();
}
DxLib_End();
//動画保存
writer.release();
//ユーザーにffmpegを入れてもらい、コマンドでmp4に
system("ffmpeg -y -i _temp.avi -i _temp.wav movie.mp4");
//一時ファイル削除
DeleteFile("_temp.wav");
DeleteFile("_temp.avi");
return 0;
}
struct PS_INPUT
{
float4 DiffuseColor : COLOR0 ;
float4 SpecularColor : COLOR1 ;
float2 TextureCoord0 : TEXCOORD0 ;
float2 TextureCoord1 : TEXCOORD1 ;
} ;
struct PS_OUTPUT
{
float4 Output : COLOR0 ;
} ;
sampler Texture : register( s0 ) ;
PS_OUTPUT main( PS_INPUT PSInput )
{
PS_OUTPUT PSOutput ;
float4 TextureColor;
float4 OutputColor;
TextureColor = tex2D( Texture , PSInput.TextureCoord0 );
OutputColor.b = TextureColor.r;
OutputColor.g = TextureColor.g;
OutputColor.r = TextureColor.b;
OutputColor.a = TextureColor.a;
PSOutput.Output = OutputColor;
return PSOutput;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment