4.3 stability应用程序
程序员文章站
2022-06-22 09:52:35
...
在4.2 flashlight基础上的改进
kernel.h
#pragma once
#ifndef KERNEL_H
#define KERNEL_H
struct uchar4;
struct int2;
void kernelLauncher(uchar4 *d_out, int w, int h, float p, int s);
#endif // !KERNEL_H
kernel.cu
#include "kernel.h"
#define TX 32//线程数
#define TY 32
#define LEN 5.f//空间比例因子
#define TIME_STEP 0.005f//时间步长
#define FINAL_TIME 10.f//时间间隔
__device__ float scale(int i, int w)//限定像素值的坐标范围[-LEN,LEN]
{
return 2 * LEN*(((1.f*i) / w) - 0.5f);
}
__device__ float f(float x, float y, float param, float sys)//速度的变化率
{
if (sys==1)//线性阻尼振荡器
{
return x - 2 * param*y;
}
if (sys == 2)//负有效刚度线性振荡器(接近于倒立摆位的情况)
{
return -x + param*(1 - x*x)*y;
}
else
return -x - 2 * param*y;//范德堡尔振荡器,具有一个非线性阻尼项
}
//对一个给定的初始状态进行模拟,并且根据轨迹的位置在模拟区间结尾返回一个float2型的值
__device__ float2 euler(float x, float y, float dt, float tFinal, float param, float sys)
{
float dx = 0.f, dy = 0.f;
for (float t = 0; t < tFinal; t+=dt)
{
dx = dt*y;
dy = dt*f(x, y, param, sys);
x += dx;
y += dy;
}
return make_float2(x, y);
}
__device__ unsigned char clip(int n)
{
return n > 255 ? 255 : (n < 0 ? 0 : n);
}
__global__ void stabImageKernel(uchar4 *d_out, int w, int h, float p, int s)//阻尼参数p 振荡器类型s
{
const int c = blockIdx.x*blockDim.x + threadIdx.x;
const int r = blockIdx.x*blockDim.y + threadIdx.y;
if ((c>=w)||(r>=h))
{
return;
}
const int i = c + r*w;
const float x0 = scale(c, w);
const float y0 = scale(r, h);
const float dist_0 = sqrt(x0*x0 + y0*y0);
const float2 pos = euler(x0, y0, TIME_STEP, FINAL_TIME, p, s);
const float dist_f = sqrt(pos.x*pos.x+pos.y*pos.y);//基于距离比较分配阴影值
const float dist_r = dist_f / dist_0;
d_out[i].x = clip(dist_r * 255);//red逐渐远离平衡(即否决稳定的其他投票)
d_out[i].y = ((c == w / 2));//green
d_out[i].z = clip((1 / dist_r) * 255);//blue代表衰减到平衡(即稳定的投票)
d_out[i].w = 255;
}
void kernelLauncher(uchar4 *d_out, int w, int h, float p, int s)
{
const dim3 blockSize(TX, TY);
const dim3 gridSize = dim3((w + TX - 1) / TX, (h + TY - 1) / TY);
stabImageKernel << <gridSize, blockSize >> > (d_out, w, h, p, s);
}
interactions.h
#pragma once
#ifndef INTERACTIONS_H
#define INTERACTIONS_H
#define W 600//图像维度
#define H 600
#define DELTA 5//每按下箭头键参考点移动的距离(以像素为单位)
//#define TITLE_STRING "flashlight:distance image display app"//标题栏中显示的文本
#define DELTA_P 0.1f
#define TITLE_STRING "Stablility"
int sys = 0;
float param = 0.1f;
void keyboard(unsigned char key, int x, int y)
{
if (key==27)
{
exit(0);
}
if (key=='0')
{
sys = 0;
}
if (key == '1')
sys = 1;
if (key == '2')
sys = 2;
glutPostRedisplay();
}
void handleSpecialKeypress(int key, int x, int y)
{
if (key==GLUT_KEY_DOWN)
{
param -= DELTA_P;
}
if (key==GLUT_KEY_UP)
{
param += DELTA_P;//调节阻尼值
}
glutPostRedisplay();
}
void mouseMove(int x, int y) { return; }
void mouseDrag(int x, int y) { return; }
void printInstructions()
{
printf("Stability visualizer\n");
printf("Use number keys to select system:\n");
printf("\t0: linear oscillator:positive stiffness\n");
printf("\t1: linear oscillator:negative stiffness\n");
printf("\t2: van der Pol oscillator:nonlinear damping\n");
printf("up/down arrow keys adjust parameter value\n\n");
printf("Choose the van der Pol (sys=2)\n");
printf("Keep up arrow key depressed and watch the show.\n");
}
#endif
main.cpp中只对render()函数进行了改动,标题栏信息和内核启动调用
void render()//创造属于自己的CUDA/OPENGL互操作应用程序时,唯一需要改变的就是render函数
{
uchar4 *d_out = 0;
cudaGraphicsMapResources(1, &cuda_pbo_resource, 0);
cudaGraphicsResourceGetMappedPointer((void**)&d_out, NULL, cuda_pbo_resource);
kernelLauncher(d_out, W, H, param, sys);
cudaGraphicsUnmapResources(1, &cuda_pbo_resource, 0);
char title[64];
sprintf(title, "Stability:param=%.1f,sys=%d", param, sys);
glutSetWindowTitle(title);
}
运行结果: